These instructions assume you are already familiar with the testing infrastructure and know how to write a standard HTTP/1.1 test.
On top of the standard main handler that the H1 server offers, the H2 server also offers support for specific frame handlers in the Python scripts. Currently there is support for for handle_headers and handle_data. Unlike the main handler, these  are run whenever the server receives a HEADERS frame (RequestReceived event) or a DATA frame (DataReceived event). main can still be used, but it will be run after the server has received the request in its entirety.
Here is what a Python script for a test might look like:
def handle_headers(frame, request, response): if request.headers["test"] == "pass": response.status = 200 response.headers.update([('test', 'passed')]) response.write_status_headers() else: response.status = 403 response.headers.update([('test', 'failed')]) response.write_status_headers() response.writer.end_stream() def handle_data(frame, request, response): response.writer.write_data(frame.data[::-1]) def main(request, response): response.writer.write_data('\nEnd of File', last=True)
The above script is fairly simple:
handle_headers is run.handle_data. This will simply reverse the data and send it back.main is run which will send one last DATA frame and signal its the end of the stream.The H2Response API is pretty much the same as the H1 variant, the main API difference lies in the H2ResponseWriter which is accessed through response.writer
write_headers(self, headers, status_code, status_message=None, stream_id=None, last=False):Write a HEADER frame using the H2 Connection object, will only work if the stream is in a state to send HEADER frames. This will automatically format the headers so that pseudo headers are at the start of the list and correctly prefixed with ‘:’. Since this using the H2 Connection object, it requires that the stream is in the correct state to be sending this frame.
Note: Will raise ProtocolErrors if pseudo headers are missing.
Parameters
write_data(self, item, last=False, stream_id=None):Write a DATA frame using the H2 Connection object, will only work if the stream is in a state to send DATA frames. Uses flow control to split data into multiple data frames if it exceeds the size that can be in a single frame. Since this using the H2 Connection object, it requires that the stream is in the correct state to be sending this frame.
Parameters
write_push(self, promise_headers, push_stream_id=None, status=None, response_headers=None, response_data=None):This will write a push promise to the request stream. If you do not provide headers and data for the response, then no response will be pushed, and you should send them yourself using the ID returned from this function.
Parameters
Returns: The ID of the push stream
write_raw_header_frame(self, headers, stream_id=None, end_stream=False, end_headers=False, frame_cls=HeadersFrame):Unlike write_headers, this does not check to see if a stream is in the correct state to have HEADER frames sent through to it. It also won't force the order of the headers or make sure pseudo headers are prefixed with ‘:’. It will build a HEADER frame and send it without using the H2 Connection object other than to HPACK encode the headers.
Note: The
frame_clsparameter is so that this class can be reused bywrite_raw_continuation_frame, as their construction is identical.
True to add END_STREAM flag to frameTrue to add END_HEADERS flag to framewrite_raw_data_frame(self, data, stream_id=None, end_stream=False):Unlike write_data, this does not check to see if a stream is in the correct state to have DATA frames sent through to it. It will build a DATA frame and send it without using the H2 Connection object. It will not perform any flow control checks.
write_raw_continuation_frame(self, headers, stream_id=None, end_headers=False):This provides the ability to create and write a CONTINUATION frame to the stream, which is not exposed by write_headers as the h2 library handles the split between HEADER and CONTINUATION internally. Will perform HPACK encoding on the headers. It also ignores the state of the stream.
This calls write_raw_data_frame with frame_cls=ContinuationFrame since the HEADER and CONTINUATION frames are constructed in the same way.
end_stream(self, stream_id=None):Ends the stream with the given ID, or the one that request was made on if no ID given.