Skip to content

Commit aa2d885

Browse files
aranchromium-wpt-export-bot
authored andcommitted
Move the WebTransport headers test to external/wpt
R=flackr@chromium.org, ricea@chromium.org Change-Id: I844c3180fccad46b0f0120467c2a71dc4e3f085a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8265548 Reviewed-by: Adam Rice <ricea@chromium.org> Reviewed-by: Robert Flack <flackr@chromium.org> Commit-Queue: Adam Rice <ricea@chromium.org> Cr-Commit-Position: refs/heads/main@{#1682887}
1 parent 17fb269 commit aa2d885

1 file changed

Lines changed: 127 additions & 0 deletions

File tree

webtransport/headers.https.any.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// META: global=window,worker
2+
// META: script=/webtransport/resources/webtransport-test-helpers.sub.js
3+
4+
promise_test(async t => {
5+
const wt = new WebTransport(webtransport_url('echo-request-headers.py'));
6+
t.add_cleanup(() => wt.close());
7+
assert_equals(wt.responseHeaders, null,
8+
'responseHeaders is null synchronously after construction');
9+
await wt.ready;
10+
}, 'responseHeaders is null before the connection is established');
11+
12+
promise_test(async t => {
13+
const wt = new WebTransport(webtransport_url('echo-request-headers.py'));
14+
t.add_cleanup(() => wt.close());
15+
await wt.ready;
16+
assert_true(wt.responseHeaders instanceof Headers,
17+
'responseHeaders is a Headers object after ready');
18+
}, 'responseHeaders is a Headers object after ready resolves');
19+
20+
promise_test(async t => {
21+
const wt = new WebTransport(
22+
webtransport_url('custom-response.py?x-test-header=hello&x-other=world'));
23+
t.add_cleanup(() => wt.close());
24+
await wt.ready;
25+
assert_equals(wt.responseHeaders.get('x-test-header'), 'hello');
26+
assert_equals(wt.responseHeaders.get('x-other'), 'world');
27+
}, 'responseHeaders exposes server-sent response headers');
28+
29+
promise_test(async t => {
30+
const wt =
31+
new WebTransport(webtransport_url('custom-response.py?wt-protocol=foo'));
32+
t.add_cleanup(() => wt.close());
33+
await wt.ready;
34+
assert_false(wt.responseHeaders.has('wt-protocol'),
35+
'wt-protocol must be stripped from responseHeaders');
36+
}, 'wt-protocol is stripped from responseHeaders');
37+
38+
promise_test(async t => {
39+
// https://fetch.spec.whatwg.org/#forbidden-response-header-name
40+
const wt = new WebTransport(
41+
webtransport_url('custom-response.py?set-cookie=probe%3D1'));
42+
t.add_cleanup(() => wt.close());
43+
await wt.ready;
44+
assert_false(
45+
wt.responseHeaders.has('set-cookie'),
46+
'Set-Cookie must not be exposed via WebTransport.responseHeaders');
47+
}, 'Set-Cookie is stripped from responseHeaders');
48+
49+
promise_test(async t => {
50+
const wt = new WebTransport(webtransport_url('echo-request-headers.py'),
51+
{headers: {'x-client-header': 'sent'}});
52+
t.add_cleanup(() => wt.close());
53+
await wt.ready;
54+
55+
const streams = await wt.incomingUnidirectionalStreams;
56+
const stream_reader = streams.getReader();
57+
const {value: recv_stream} = await stream_reader.read();
58+
stream_reader.releaseLock();
59+
const request_headers = await read_stream_as_json(recv_stream);
60+
61+
// HTTP/3 requires lowercase field names (RFC 9114 §4.2), so the header
62+
// should arrive at the server lowercased regardless of the source casing.
63+
assert_equals(request_headers['x-client-header'], 'sent',
64+
'custom header forwarded to the server');
65+
assert_equals(request_headers['X-Client-Header'], undefined,
66+
'custom header is not forwarded with the original casing');
67+
}, 'headers option forwards a custom header to the server, lowercased');
68+
69+
promise_test(async t => {
70+
// Cookie is on the Fetch forbidden request-header list; per Fetch spec it
71+
// is silently dropped rather than throwing, so the connection succeeds but
72+
// the header must not reach the server.
73+
const wt = new WebTransport(webtransport_url('echo-request-headers.py'),
74+
{headers: {'Cookie': 'probe=forbidden'}});
75+
t.add_cleanup(() => wt.close());
76+
await wt.ready;
77+
78+
const streams = await wt.incomingUnidirectionalStreams;
79+
const stream_reader = streams.getReader();
80+
const {value: recv_stream} = await stream_reader.read();
81+
stream_reader.releaseLock();
82+
const request_headers = await read_stream_as_json(recv_stream);
83+
84+
assert_not_equals(
85+
request_headers['cookie'], 'probe=forbidden',
86+
'user-supplied Cookie must be silently dropped, not forwarded');
87+
}, 'Forbidden request-header names are silently dropped from the headers option');
88+
89+
test(() => {
90+
assert_throws_js(TypeError, () => new WebTransport('https://localhost:0/', {
91+
headers: {'wt-available-protocols': 'test'}
92+
}));
93+
}, 'wt-available-protocols header throws TypeError');
94+
95+
test(() => {
96+
assert_throws_js(TypeError, () => new WebTransport('https://localhost:0/', {
97+
headers: {'WT-Available-Protocols': 'test'}
98+
}));
99+
}, 'wt-available-protocols header throws TypeError (upper case)');
100+
101+
test(() => {
102+
assert_throws_js(TypeError, () => new WebTransport('https://localhost:0/', {
103+
headers: {'Wt-AVAILABLE-protocols': 'test'}
104+
}));
105+
}, 'wt-available-protocols header throws TypeError (mixed case)');
106+
107+
function constructAndClose(options) {
108+
const wt = new WebTransport('https://localhost:0/', options);
109+
// Swallow the unhandled rejections from the unreachable URL.
110+
wt.ready.catch(() => {});
111+
wt.closed.catch(() => {});
112+
wt.close();
113+
}
114+
115+
test(() => {
116+
constructAndClose({headers: [['x-foo', 'bar'], ['x-baz', 'qux']]});
117+
}, 'HeadersInit sequence-of-sequences form is accepted');
118+
119+
test(() => {
120+
constructAndClose({headers: [['x-dup', 'one'], ['x-dup', 'two']]});
121+
}, 'Duplicate header names in sequence form are accepted');
122+
123+
test(() => {
124+
assert_throws_js(TypeError,
125+
() => new WebTransport('https://localhost:0/',
126+
{headers: [['only-one-element']]}));
127+
}, 'HeadersInit sequence with wrong inner length throws TypeError');

0 commit comments

Comments
 (0)