def flow_to_exchange(flow):
    req = construct_request(flow)
    resp = construct_response(flow)
    exch = httpolice.Exchange(req, [resp] if resp else [])
    exch.silence([int(id_) for id_ in ctx.options.httpolice_silence])
    httpolice.check_exchange(exch)
    return exch
Esempio n. 2
0
def test_prefer():
    [exch1] = load_from_file('funny_prefer')
    assert exch1.request.headers.prefer.value == [
        Parametrized(Parametrized(prefer.handling, u'lenient'), [
            Parametrized(u'param1', u"this is a parameter to 'handling'!"),
            Parametrized(u'param2', None),
        ]),
        Unavailable(b'BWS-is-not-parsed = because-see-errata'),
        Parametrized(Parametrized(prefer.wait, 600), []),
        Parametrized(Parametrized(u'my-pref', None), [
            None,
            None,
            Parametrized(u'foo', None),
            None,
            None,
            Parametrized(u'bar', None),
        ]),
        Parametrized(Parametrized(prefer.respond_async, None), []),
        Parametrized(Parametrized(prefer.wait, 0), []),
        Parametrized(
            Parametrized(prefer.return_, Unavailable(b'something-else')), []),
    ]
    assert exch1.request.headers.prefer.wait == 600
    assert exch1.request.headers.prefer.respond_async
    assert isinstance(exch1.request.headers.prefer.return_, Unavailable)
    assert exch1.request.headers.prefer[u'quux'] is None
    assert isinstance(
        exch1.responses[0].headers.preference_applied.respond_async,
        Unavailable)
    check_exchange(exch1)
    buf = io.BytesIO()
    text_report([exch1], buf)
    assert b'Preference-Applied: respond-async=true was not requested' \
        in buf.getvalue()           # not "respond-async=Unavailable"
Esempio n. 3
0
def test_informational_response_after_final():
    exch = Exchange(
        Request(
            u'https',
            u'POST',
            u'/process/',
            u'HTTP/1.1',
            [
                (u'Host', b'example.com'),
                (u'User-Agent', b'demo'),
                (u'Content-Length', b'14'),
                (u'Content-Type', b'text/plain'),
                (u'Expect', b'100-continue'),
            ],
            b'Hello world!\r\n',
        ),
        [
            Response(u'HTTP/1.1', 100, u'Continue', [], b''),
            Response(
                u'HTTP/1.1',
                204,
                u'No Content',
                [(u'Date', b'Fri, 02 Feb 2018 15:44:33 GMT')],
                b'',
            ),
            Response(u'HTTP/1.1', 102, u'Processing', [], b''),
        ],
    )
    check_exchange(exch)
    assert [notice.id for notice in exch.request.notices] == []
    assert [notice.id for notice in exch.responses[0].notices] == []
    assert [notice.id for notice in exch.responses[1].notices] == []
    assert [notice.id for notice in exch.responses[2].notices] == [1304]
Esempio n. 4
0
def test_informational_response_after_final():
    exch = Exchange(
        Request(
            u'https', u'POST', u'/process/', u'HTTP/1.1',
            [
                (u'Host', b'example.com'),
                (u'User-Agent', b'demo'),
                (u'Content-Length', b'14'),
                (u'Content-Type', b'text/plain'),
                (u'Expect', b'100-continue'),
            ],
            b'Hello world!\r\n',
        ),
        [
            Response(
                u'HTTP/1.1', 100, u'Continue', [], b''
            ),
            Response(
                u'HTTP/1.1', 204, u'No Content',
                [(u'Date', b'Fri, 02 Feb 2018 15:44:33 GMT')],
                b'',
            ),
            Response(
                u'HTTP/1.1', 102, u'Processing', [], b''
            ),
        ],
    )
    check_exchange(exch)
    assert [notice.id for notice in exch.request.notices] == []
    assert [notice.id for notice in exch.responses[0].notices] == []
    assert [notice.id for notice in exch.responses[1].notices] == []
    assert [notice.id for notice in exch.responses[2].notices] == [1304]
Esempio n. 5
0
def response(context, flow):
    req = construct_request(flow)
    resp = construct_response(flow)
    exch = httpolice.Exchange(req, [resp])
    if context.args.silence:
        exch.silence(context.args.silence)
    httpolice.check_exchange(exch)
    context.exchanges.append(exch)
Esempio n. 6
0
def test_fuzz(i):
    orig_state = random.getstate()
    random.seed(123456789 + i)      # Some arbitrary, but deterministic number.
    exch = make_exchange()
    random.setstate(orig_state)

    check_exchange(exch)
    text_report([exch], io.BytesIO())
    html_report([exch], io.BytesIO())
Esempio n. 7
0
def test_fuzz(i):
    orig_state = random.getstate()
    random.seed(123456789 + i)  # Some arbitrary, but deterministic number.
    exch = make_exchange()
    random.setstate(orig_state)

    check_exchange(exch)
    text_report([exch], io.BytesIO())
    html_report([exch], io.BytesIO())
Esempio n. 8
0
def har_input(data):
    creator = data['log']['creator']['name']
    bad_exchanges = []
    exchanges = [
        _process_entry(entry, creator, 'from chrome')
        for entry in data['log']['entries']
    ]

    # check
    for exch in exchanges:
        httpolice.check_exchange(exch)
        if any(notice.severity > httpolice.Severity.debug
               for msg in [exch.request] + exch.responses
               for notice in msg.notices):
            bad_exchanges.append(exch)

    # report
    out = StringIO.StringIO()
    if bad_exchanges:
        httpolice.html_report(bad_exchanges, out)
    return out
Esempio n. 9
0
def test_fuzz(i, state=None):
    if state is None:
        state = random.getstate()
    else:
        random.setstate(state)

    req = random.choice([
        None,
        Request(random.choice(schemes),
                random.choice(methods),
                make_request_target(),
                random.choice(versions),
                make_headers(max_num=5),
                make_body(),
                make_headers(max_num=2))
    ])
    resps = [
        Response(random.choice(versions),
                 make_status_code(),
                 make_reason_phrase(),
                 make_headers(max_num=5),
                 make_body(),
                 make_headers(max_num=2))
        for _ in range(random.randint(0, 2))
    ]

    try:
        exch = Exchange(req, resps)
        check_exchange(exch)
        text_report([exch], six.BytesIO())
        html_report([exch], six.BytesIO())
    except Exception:
        filename = 'fuzz-state-%02d.pickle' % i
        with io.open(filename, 'wb') as f:
            pickle.dump(state, f)
        raise
Esempio n. 10
0
    def process_response(self, request, response):
        if not get_setting('ENABLE'):
            return response

        # Importing `httpolice` can execute a lot of code,
        # so we only do it when it's really time for action.
        import httpolice

        req_method = _force_text(request.method)
        req_headers = httpolice.helpers.headers_from_cgi(request.META)
        req_target = _force_text(request.path)
        if request.META.get('QUERY_STRING'):
            req_target += u'?' + _force_text(request.META['QUERY_STRING'])

        try:
            # This can raise `django.http.request.RawPostDataException`, saying
            # "You cannot access body after reading from request's data stream"
            req_body = request.body
        except Exception:
            # ...but `RawPostDataException` is not documented in Django API,
            # so catch everything.
            req_body = None

        # A ``Content-Type`` of ``text/plain`` is automatically added
        # to requests that have none (such as GET requests).
        if req_body == b'' and req_method in [u'GET', u'HEAD', u'DELETE']:
            req_headers = [entry for entry in req_headers
                           if entry != (u'Content-Type', b'text/plain')]

        req = httpolice.Request(
            scheme=_force_text(request.scheme),
            method=req_method,
            target=req_target,
            version=None,
            header_entries=req_headers,
            body=req_body,
        )

        if req_method == u'HEAD':
            # Body is automatically stripped from responses to HEAD,
            # but not at this point in the response lifecycle.
            resp_body = b''
        elif response.streaming:
            resp_body = None        # Unknown.
        else:
            resp_body = response.content

        resp = httpolice.Response(
            version=None,
            status=response.status_code,
            reason=_force_text(response.reason_phrase),
            header_entries=[
                (_force_text(name), value)
                for (name, value) in response.items()],
            body=resp_body,
        )

        exchange = httpolice.Exchange(req, [resp])
        exchange.silence(get_setting('SILENCE'))
        httpolice.check_exchange(exchange)
        backlog.appendleft(exchange)

        if get_setting('RAISE') and any(notice.severity == httpolice.ERROR
                                        for notice in resp.notices):
            raise ProtocolError(exchange)

        return response
Esempio n. 11
0
import io
import httpolice

exchanges = [
    httpolice.Exchange(
        httpolice.Request(u'https', u'GET', u'/index.html', u'HTTP/1.1',
                          [(u'Host', b'example.com')], b''),
        [
            httpolice.Response(u'HTTP/1.1', 401, u'Unauthorized',
                               [(u'Content-Type', b'text/plain')], b'No way!'),
        ])
]

bad_exchanges = []

for exch in exchanges:
    exch.silence([1089, 1227])  # Errors we don't care about
    httpolice.check_exchange(exch)
    if any(notice.severity > httpolice.Severity.comment
           for resp in exch.responses  # We only care about responses
           for notice in resp.notices):
        bad_exchanges.append(exch)

if bad_exchanges:
    with io.open('report.html', 'wb') as f:
        httpolice.html_report(bad_exchanges, f)
    print('%d exchanges had problems; report written to file' %
          len(bad_exchanges))
Esempio n. 12
0
# ``conf.py`` "can execute arbitrarily complex code", so maybe it's OK.

# See also: https://stackoverflow.com/q/38547509/200445

if os.path.exists('_extra'):
    shutil.rmtree('_extra')
os.mkdir('_extra')

with io.open('_extra/notices.html', 'wb') as notices_file:
    httpolice.reports.html.list_notices(notices_file)

with io.open('_extra/showcase.html', 'wb') as showcase_file:
    exchanges = list(httpolice.inputs.combined_input(
        ['../test/combined_data/showcase.https']))
    for exch in exchanges:
        httpolice.check_exchange(exch)
    httpolice.html_report(exchanges, showcase_file)


# -- General configuration ------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    'sphinx.ext.autodoc',
]