mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Update web-platform-tests to revision ab64b78a8f6777a1d95d8d1d4bba9ccdbecf94ea
This commit is contained in:
parent
da36740f0b
commit
394aced19f
713 changed files with 12430 additions and 12632 deletions
155
tests/wpt/web-platform-tests/docs/_writing-tests/h2tests.md
Normal file
155
tests/wpt/web-platform-tests/docs/_writing-tests/h2tests.md
Normal file
|
@ -0,0 +1,155 @@
|
|||
# Writing H2 Tests
|
||||
> <b>Important:</b> The HTTP/2.0 server requires you to have Python 2.7.10+
|
||||
and OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
|
||||
[TLS ALPN](https://tools.ietf.org/html/rfc7301) extension, which is only supported in [OpenSSL 1.0.2](https://www.openssl.org/news/openssl-1.0.2-notes.html) and up.
|
||||
|
||||
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:
|
||||
```python
|
||||
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:
|
||||
1. Upon receiving the HEADERS frame, `handle_headers` is run.
|
||||
- This checks for a header called 'test' and checks if it is set to 'pass'.
|
||||
If true, it will immediately send a response header, otherwise it responds
|
||||
with a 403 and ends the stream.
|
||||
2. Any DATA frames received will then be handled by `handle_data`. This will
|
||||
simply reverse the data and send it back.
|
||||
3. Once the request has been fully received, `main` is run which will send
|
||||
one last DATA frame and signal its the end of the stream.
|
||||
|
||||
## Response Writer API ##
|
||||
|
||||
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.
|
||||
|
||||
> <b>Note</b>: Will raise ProtocolErrors if pseudo headers are missing.
|
||||
|
||||
- <b>Parameters</b>
|
||||
|
||||
- <b>headers</b>: List of (header, value) tuples
|
||||
- <b>status_code</b>: The HTTP status code of the response
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
||||
- <b>last</b>: Flag to signal if this is the last frame in stream.
|
||||
|
||||
---
|
||||
|
||||
#### `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.
|
||||
|
||||
- <b>Parameters</b>
|
||||
|
||||
- <b>item</b>: The content of the DATA frame
|
||||
- <b>last</b>: Flag to signal if this is the last frame in stream.
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
||||
|
||||
---
|
||||
|
||||
#### `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.
|
||||
|
||||
- <b>Parameters</b>
|
||||
- <b>promise_headers</b>: A list of header tuples that matches what the client would use to
|
||||
request the pushed response
|
||||
- <b>push_stream_id</b>: The ID of the stream the response should be pushed to. If none given, will
|
||||
use the next available id.
|
||||
- <b>status</b>: The status code of the response, REQUIRED if response_headers given
|
||||
- <b>response_headers</b>: The headers of the response
|
||||
- <b>response_data</b>: The response data.
|
||||
|
||||
- <b>Returns</b>: 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.
|
||||
|
||||
> <b>Note</b>: The `frame_cls` parameter is so that this class can be reused
|
||||
by `write_raw_continuation_frame`, as their construction is identical.
|
||||
|
||||
- <b>Parameters</b>
|
||||
- <b>headers</b>: List of (header, value) tuples
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
||||
- <b>end_stream</b>: Set to `True` to add END_STREAM flag to frame
|
||||
- <b>end_headers</b>: Set to `True` to add END_HEADERS flag to frame
|
||||
|
||||
---
|
||||
|
||||
#### `write_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.
|
||||
|
||||
- <b>Parameters</b>
|
||||
- <b>data</b>: The data to be sent in the frame
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
||||
- <b>end_stream</b>: Set to True to add END_STREAM flag to frame
|
||||
|
||||
---
|
||||
|
||||
#### `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.
|
||||
|
||||
- <b>Parameters</b>:
|
||||
- <b>headers</b>: List of (header, value) tuples
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
||||
- <b>end_headers</b>: Set to True to add END_HEADERS flag to frame
|
||||
|
||||
---
|
||||
|
||||
#### `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.
|
||||
|
||||
- <b>Parameters</b>
|
||||
- <b>stream_id</b>: Id of stream to send frame on. Will use the request stream ID if None
|
|
@ -94,4 +94,17 @@ of the response. For details see the
|
|||
[wptserve documentation](https://wptserve.readthedocs.org).
|
||||
|
||||
|
||||
### Writing tests for HTTP/2.0
|
||||
|
||||
The server now has a prototype HTTP/2.0 server which gives you access to
|
||||
some of the HTTP/2.0 specific functionality. Currently, the server is off
|
||||
by default and needs to be run using `./wpt serve --h2` in order to enable it.
|
||||
The HTTP/2.0 server supports handlers that work per-frame; these, along with the
|
||||
API are documented in [Writing H2 Tests][h2tests]
|
||||
|
||||
> <b>Important:</b> The HTTP/2.0 server requires you to have Python 2.7.10+
|
||||
and OpenSSL 1.0.2+. This is because HTTP/2.0 is negotiated using the
|
||||
[TLS ALPN](https://tools.ietf.org/html/rfc7301) extension, which is only supported in [OpenSSL 1.0.2](https://www.openssl.org/news/openssl-1.0.2-notes.html) and up.
|
||||
|
||||
[file names]: {{ site.baseurl }}{% link _writing-tests/file-names.md %}
|
||||
[h2tests]: {{ site.baseurl }}{% link _writing-tests/h2tests.md %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue