示例#1
0
def test_response_trailers(tctx: Context, open_h2_server_conn: Server, stream):
    playbook, cff = start_h2_client(tctx)
    tctx.server = open_h2_server_conn
    sff = FrameFactory()

    def enable_streaming(flow: HTTPFlow):
        flow.response.stream = bool(stream)

    flow = Placeholder(HTTPFlow)
    (
        playbook
        >> DataReceived(tctx.client,
                        cff.build_headers_frame(example_request_headers, flags=["END_STREAM"]).serialize())
        << http.HttpRequestHeadersHook(flow)
        >> reply()
        << http.HttpRequestHook(flow)
        >> reply()
        << SendData(tctx.server, Placeholder(bytes))
        # a conforming h2 server would send settings first, we disregard this for now.
        >> DataReceived(tctx.server, sff.build_headers_frame(example_response_headers).serialize() +
                        sff.build_data_frame(b"Hello, World!").serialize())
        << http.HttpResponseHeadersHook(flow)
        >> reply(side_effect=enable_streaming)
    )
    if stream:
        playbook << SendData(
            tctx.client,
            cff.build_headers_frame(example_response_headers).serialize() +
            cff.build_data_frame(b"Hello, World!").serialize()
        )
    assert (
        playbook
        >> DataReceived(tctx.server, sff.build_headers_frame(example_response_trailers, flags=["END_STREAM"]).serialize())
        << http.HttpResponseHook(flow)
    )
    assert flow().response.trailers
    del flow().response.trailers["resp-trailer-a"]
    if stream:
        assert (
            playbook
            >> reply()
            << SendData(tctx.client,
                        cff.build_headers_frame(example_response_trailers[1:], flags=["END_STREAM"]).serialize())
        )
    else:
        assert (
            playbook
            >> reply()
            << SendData(tctx.client,
                        cff.build_headers_frame(example_response_headers).serialize() +
                        cff.build_data_frame(b"Hello, World!").serialize() +
                        cff.build_headers_frame(example_response_trailers[1:], flags=["END_STREAM"]).serialize()))
示例#2
0
def test_max_concurrency(tctx):
    playbook, cff = start_h2_client(tctx)
    server = Placeholder(Server)
    req1_bytes = Placeholder(bytes)
    settings_ack_bytes = Placeholder(bytes)
    req2_bytes = Placeholder(bytes)
    playbook.hooks = False
    sff = FrameFactory()

    assert (playbook >> DataReceived(
        tctx.client,
        cff.build_headers_frame(example_request_headers,
                                flags=["END_STREAM"],
                                stream_id=1).serialize()) <<
            OpenConnection(server) >> reply(None, side_effect=make_h2) <<
            SendData(server, req1_bytes) >> DataReceived(
                server,
                sff.build_settings_frame({
                    h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS:
                    1
                }).serialize()) << SendData(
                    server, settings_ack_bytes) >> DataReceived(
                        tctx.client,
                        cff.build_headers_frame(example_request_headers,
                                                flags=["END_STREAM"],
                                                stream_id=3).serialize())
            # Can't send it upstream yet, all streams in use!
            >> DataReceived(
                server,
                sff.build_headers_frame(example_response_headers,
                                        flags=["END_STREAM"],
                                        stream_id=1).serialize())
            # But now we can!
            << SendData(server, req2_bytes) <<
            SendData(tctx.client, Placeholder(bytes)) >> DataReceived(
                server,
                sff.build_headers_frame(example_response_headers,
                                        flags=["END_STREAM"],
                                        stream_id=3).serialize()) << SendData(
                                            tctx.client, Placeholder(bytes)))
    settings, req1 = decode_frames(req1_bytes())
    settings_ack, = decode_frames(settings_ack_bytes())
    req2, = decode_frames(req2_bytes())

    assert type(settings) == hyperframe.frame.SettingsFrame
    assert type(req1) == hyperframe.frame.HeadersFrame
    assert type(settings_ack) == hyperframe.frame.SettingsFrame
    assert type(req2) == hyperframe.frame.HeadersFrame
    assert req1.stream_id == 1
    assert req2.stream_id == 3
示例#3
0
def h2_frames(draw):
    ff = FrameFactory()
    headers1 = ff.build_headers_frame(headers=draw(h2_headers()))
    headers1.flags.clear()
    headers1.flags |= draw(h2_flags)
    headers2 = ff.build_headers_frame(headers=draw(h2_headers()),
                                      depends_on=draw(h2_stream_ids),
                                      stream_weight=draw(integers(0, 255)),
                                      exclusive=draw(booleans()))
    headers2.flags.clear()
    headers2.flags |= draw(h2_flags)
    settings = ff.build_settings_frame(settings=draw(
        dictionaries(
            keys=sampled_from(SettingCodes),
            values=integers(0, 2**32 - 1),
            max_size=5,
        )),
                                       ack=draw(booleans()))
    continuation = ff.build_continuation_frame(header_block=ff.encoder.encode(
        draw(h2_headers())),
                                               flags=draw(h2_flags))
    goaway = ff.build_goaway_frame(draw(h2_stream_ids))
    push_promise = ff.build_push_promise_frame(
        stream_id=draw(h2_stream_ids_nonzero),
        promised_stream_id=draw(h2_stream_ids),
        headers=draw(h2_headers()))
    rst = ff.build_rst_stream_frame(draw(h2_stream_ids_nonzero))
    prio = ff.build_priority_frame(
        stream_id=draw(h2_stream_ids_nonzero),
        weight=draw(integers(0, 255)),
        depends_on=draw(h2_stream_ids),
        exclusive=draw(booleans()),
    )
    data1 = ff.build_data_frame(draw(binary()), draw(h2_flags))
    data2 = ff.build_data_frame(draw(binary()),
                                draw(h2_flags),
                                stream_id=draw(h2_stream_ids_nonzero))
    window_update = ff.build_window_update_frame(draw(h2_stream_ids),
                                                 draw(integers(0, 2**32 - 1)))

    frames = draw(
        lists(sampled_from([
            headers1, headers2, settings, continuation, goaway, push_promise,
            rst, prio, data1, data2, window_update
        ]),
              min_size=1,
              max_size=11))
    return b"".join(x.serialize() for x in frames)
示例#4
0
def test_simple(tctx):
    playbook, cff = start_h2_client(tctx)
    flow = Placeholder(HTTPFlow)
    server = Placeholder(Server)
    initial = Placeholder(bytes)
    assert (playbook >> DataReceived(
        tctx.client,
        cff.build_headers_frame(example_request_headers, flags=[
            "END_STREAM"
        ]).serialize()) << http.HttpRequestHeadersHook(flow) >> reply() <<
            http.HttpRequestHook(flow) >> reply() << OpenConnection(server) >>
            reply(None, side_effect=make_h2) << SendData(server, initial))
    frames = decode_frames(initial())
    assert [type(x) for x in frames] == [
        hyperframe.frame.SettingsFrame,
        hyperframe.frame.HeadersFrame,
    ]
    sff = FrameFactory()
    assert (
        playbook
        # a conforming h2 server would send settings first, we disregard this for now.
        >> DataReceived(
            server,
            sff.build_headers_frame(example_response_headers).serialize()) <<
        http.HttpResponseHeadersHook(flow) >> reply() >> DataReceived(
            server,
            sff.build_data_frame(b"Hello, World!", flags=["END_STREAM"
                                                          ]).serialize()) <<
        http.HttpResponseHook(flow) >> reply() << SendData(
            tctx.client,
            cff.build_headers_frame(example_response_headers).serialize() +
            cff.build_data_frame(b"Hello, World!").serialize() +
            cff.build_data_frame(b"", flags=["END_STREAM"]).serialize()))
    assert flow().request.url == "http://example.com/"
    assert flow().response.text == "Hello, World!"
示例#5
0
 def test_no_data_on_closed_stream(self, tctx):
     frame_factory = FrameFactory()
     req = Request.make("GET", "http://example.com/")
     resp = {":status": 200}
     assert (
         Playbook(Http2Client(tctx)) << SendData(
             tctx.server,
             Placeholder(bytes))  # preamble + initial settings frame
         >> DataReceived(
             tctx.server,
             frame_factory.build_settings_frame({}, ack=True).serialize())
         >> http.RequestHeaders(1, req, end_stream=True) << SendData(
             tctx.server,
             b"\x00\x00\x06\x01\x05\x00\x00\x00\x01\x82\x86\x84\\\x81\x07")
         >> http.RequestEndOfMessage(1) >> DataReceived(
             tctx.server,
             frame_factory.build_headers_frame(resp).serialize()) <<
         http.ReceiveHttp(Placeholder(
             http.ResponseHeaders)) >> http.RequestProtocolError(
                 1, "cancelled", code=status_codes.CLIENT_CLOSED_REQUEST) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.CANCEL).serialize()) >> DataReceived(
                     tctx.server,
                     frame_factory.build_data_frame(b"foo").serialize()) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.STREAM_CLOSED).serialize())
     )  # important: no ResponseData event here!
示例#6
0
def test_no_normalization(tctx, normalize):
    """Test that we don't normalize headers when we just pass them through."""
    tctx.options.normalize_outbound_headers = normalize
    tctx.options.validate_inbound_headers = False

    server = Placeholder(Server)
    flow = Placeholder(HTTPFlow)
    playbook, cff = start_h2_client(tctx)

    request_headers = list(example_request_headers) + [(b"Should-Not-Be-Capitalized! ", b" :) ")]
    request_headers_lower = [(k.lower(), v) for (k, v) in request_headers]
    response_headers = list(example_response_headers) + [(b"Same", b"Here")]
    response_headers_lower = [(k.lower(), v) for (k, v) in response_headers]

    initial = Placeholder(bytes)
    assert (
            playbook
            >> DataReceived(tctx.client,
                            cff.build_headers_frame(request_headers, flags=["END_STREAM"]).serialize())
            << http.HttpRequestHeadersHook(flow)
            >> reply()
            << http.HttpRequestHook(flow)
            >> reply()
            << OpenConnection(server)
            >> reply(None, side_effect=make_h2)
            << SendData(server, initial)
    )
    frames = decode_frames(initial())
    assert [type(x) for x in frames] == [
        hyperframe.frame.SettingsFrame,
        hyperframe.frame.HeadersFrame,
    ]
    assert hpack.hpack.Decoder().decode(frames[1].data, True) == request_headers_lower if normalize else request_headers

    sff = FrameFactory()
    (
            playbook
            >> DataReceived(server, sff.build_headers_frame(response_headers, flags=["END_STREAM"]).serialize())
            << http.HttpResponseHeadersHook(flow)
            >> reply()
            << http.HttpResponseHook(flow)
            >> reply()
    )
    if normalize:
        playbook << Log("Lowercased 'Same' header as uppercase is not allowed with HTTP/2.")
    hdrs = response_headers_lower if normalize else response_headers
    assert playbook << SendData(tctx.client, cff.build_headers_frame(hdrs, flags=["END_STREAM"]).serialize())

    assert flow().request.headers.fields == ((b"Should-Not-Be-Capitalized! ", b" :) "),)
    assert flow().response.headers.fields == ((b"Same", b"Here"),)
示例#7
0
def test_no_normalization(tctx):
    """Test that we don't normalize headers when we just pass them through."""

    server = Placeholder(Server)
    flow = Placeholder(HTTPFlow)
    playbook, cff = start_h2_client(tctx)

    request_headers = example_request_headers + (
        (b"Should-Not-Be-Capitalized! ", b" :) "),
    )
    response_headers = example_response_headers + (
        (b"Same", b"Here"),
    )

    initial = Placeholder(bytes)
    assert (
            playbook
            >> DataReceived(tctx.client,
                            cff.build_headers_frame(request_headers, flags=["END_STREAM"]).serialize())
            << http.HttpRequestHeadersHook(flow)
            >> reply()
            << http.HttpRequestHook(flow)
            >> reply()
            << OpenConnection(server)
            >> reply(None, side_effect=make_h2)
            << SendData(server, initial)
    )
    frames = decode_frames(initial())
    assert [type(x) for x in frames] == [
        hyperframe.frame.SettingsFrame,
        hyperframe.frame.HeadersFrame,
    ]
    assert hpack.hpack.Decoder().decode(frames[1].data, True) == list(request_headers)

    sff = FrameFactory()
    assert (
            playbook
            >> DataReceived(server, sff.build_headers_frame(response_headers, flags=["END_STREAM"]).serialize())
            << http.HttpResponseHeadersHook(flow)
            >> reply()
            << http.HttpResponseHook(flow)
            >> reply()
            << SendData(tctx.client,
                        cff.build_headers_frame(response_headers).serialize() +
                        cff.build_data_frame(b"", flags=["END_STREAM"]).serialize())
    )
    assert flow().request.headers.fields == ((b"Should-Not-Be-Capitalized! ", b" :) "),)
    assert flow().response.headers.fields == ((b"Same", b"Here"),)