Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CONNECT response WPTs for WebTransport
This CL adds 7 test cases: - establish WebTransport connection with different status codes - echo the CONNECT request headers - setting a cookie in a CONNECT request, and then making sure the "cookie" header is not echoed back The echo-request-headers server handler is also added in this CL, which sends the CONNECT request headers over a unidirectional stream. Bug: 1201569 Change-Id: I30d8092af42dc2505cadbc15bf0573f8815758bd Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3134980 Commit-Queue: Nidhi Jaju <nidhijaju@chromium.org> Reviewed-by: Kenichi Ishibashi <bashi@chromium.org> Reviewed-by: Yutaka Hirano <yhirano@chromium.org> Reviewed-by: Adam Rice <ricea@chromium.org> Cr-Commit-Position: refs/heads/main@{#918651}
- Loading branch information
1 parent
8a2b0f1
commit 23fa10b
Showing
3 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// META: global=window,worker | ||
// META: script=/common/get-host-info.sub.js | ||
// META: script=resources/webtransport-test-helpers.sub.js | ||
|
||
promise_test(async t => { | ||
const wt = new WebTransport(webtransport_url('custom-response.py?:status=200')); | ||
await wt.ready; | ||
}, 'WebTransport connection succeeds with status code 200'); | ||
|
||
promise_test(async t => { | ||
const wt = new WebTransport(webtransport_url('custom-response.py?:status=204')); | ||
await wt.ready; | ||
}, 'WebTransport connection succeeds with status code 204'); | ||
|
||
promise_test(async t => { | ||
const wt = new WebTransport(webtransport_url('custom-response.py?:status=301')); | ||
await promise_rejects_js(t, TypeError, wt.ready, 'ready promise shoud be rejected'); | ||
await promise_rejects_js(t, TypeError, wt.closed, 'closed promise should be rejected'); | ||
}, 'WebTransport connection fails with status code 301'); | ||
|
||
promise_test(async t => { | ||
const wt = new WebTransport(webtransport_url('custom-response.py?:status=401')); | ||
await promise_rejects_js(t, TypeError, wt.ready, 'ready promise should be rejected'); | ||
await promise_rejects_js(t, TypeError, wt.closed, 'closed promise should be rejected'); | ||
}, 'WebTransport connection fails with status code 401'); | ||
|
||
promise_test(async t => { | ||
const wt = new WebTransport(webtransport_url('custom-response.py?:status=404')); | ||
await promise_rejects_js(t, TypeError, wt.ready, 'ready promise should be rejected'); | ||
await promise_rejects_js(t, TypeError, wt.closed, 'closed promise should be rejected'); | ||
}, 'WebTransport connection fails with status code 404'); | ||
|
||
promise_test(async t => { | ||
// Create WebTransport session. | ||
const wt = new WebTransport(webtransport_url('echo-request-headers.py')); | ||
await wt.ready; | ||
|
||
// Read incoming unidirectional stream for echoed request headers. | ||
const streams = await wt.incomingUnidirectionalStreams; | ||
|
||
const stream_reader = streams.getReader(); | ||
const { value: recv_stream } = await stream_reader.read(); | ||
stream_reader.releaseLock(); | ||
|
||
const request_headers = await read_stream_as_json(recv_stream); | ||
|
||
// Check the standard request headers. | ||
check_and_remove_standard_headers(request_headers); | ||
}, 'Echo back request headers'); | ||
|
||
promise_test(async t => { | ||
// Create WebTransport session, and attach "Set-Cookie: foo=bar" to the response of | ||
// the handshake. | ||
const encodedSetCookie = encodeURIComponent('foo=bar'); | ||
let wt = new WebTransport(webtransport_url('custom-response.py?set-cookie=' + encodedSetCookie)); | ||
await wt.ready; | ||
|
||
wt = new WebTransport(webtransport_url('echo-request-headers.py')); | ||
await wt.ready; | ||
|
||
// Read incoming unidirectional stream for echoed request headers. | ||
const streams = await wt.incomingUnidirectionalStreams; | ||
|
||
const stream_reader = streams.getReader(); | ||
const { value: recv_stream } = await stream_reader.read(); | ||
stream_reader.releaseLock(); | ||
|
||
const request_headers = await read_stream_as_json(recv_stream); | ||
|
||
// Check cookie header is not echoed back. | ||
check_and_remove_standard_headers(request_headers); | ||
assert_equals(request_headers['cookie'], undefined); | ||
}, 'Cookie header is not echoed back'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import json | ||
|
||
|
||
def session_established(session): | ||
headers = {} | ||
for name, value in session.request_headers: | ||
headers[name.decode('utf-8')] = value.decode('utf-8') | ||
|
||
stream_id = session.create_unidirectional_stream() | ||
data = json.dumps(headers).encode('utf-8') | ||
session.send_stream_data(stream_id, data, end_stream=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// The file including this must also include /common/get-host-info.sub.js to | ||
// pick up the necessary constants. | ||
|
||
const HOST = get_host_info().ORIGINAL_HOST; | ||
const PORT = '{{ports[webtransport-h3][0]}}'; | ||
const BASE = `https://${HOST}:${PORT}`; | ||
|
||
// Create URL for WebTransport session. | ||
function webtransport_url(handler) { | ||
return `${BASE}/webtransport/handlers/${handler}`; | ||
} | ||
|
||
// Decode all chunks in a given ReadableStream. | ||
async function read_stream_as_json(stream) { | ||
const decoder = new TextDecoderStream('utf-8'); | ||
const decode_stream = stream.readable.pipeThrough(decoder); | ||
const reader = decode_stream.getReader(); | ||
|
||
let chunks = ''; | ||
while (true) { | ||
const {value: chunk, done} = await reader.read(); | ||
if (done) { | ||
break; | ||
} | ||
chunks += chunk; | ||
} | ||
reader.releaseLock(); | ||
|
||
return JSON.parse(chunks); | ||
} | ||
|
||
// Check the standard request headers and delete them, leaving any "unique" | ||
// headers to check in the test. | ||
function check_and_remove_standard_headers(headers) { | ||
assert_equals(headers[':scheme'], 'https'); | ||
delete headers[':scheme']; | ||
assert_equals(headers[':method'], 'CONNECT'); | ||
delete headers[':method']; | ||
assert_equals(headers[':authority'], `${HOST}:${PORT}`); | ||
delete headers[':authority']; | ||
assert_equals(headers[':path'], '/webtransport/handlers/echo-request-headers.py'); | ||
delete headers[':path']; | ||
assert_equals(headers[':protocol'], 'webtransport'); | ||
delete headers[':protocol']; | ||
assert_equals(headers['origin'], `${get_host_info().ORIGIN}`); | ||
delete headers['origin']; | ||
assert_equals(headers['datagram-flow-id'], '0'); | ||
delete headers['datagram-flow-id']; | ||
} |