MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1import { test, testThrows, summary } from './helpers.js';
2
3console.log('Request Tests\n');
4
5test('Request typeof', typeof Request, 'function');
6test('Request toStringTag', Object.prototype.toString.call(new Request('https://example.com/')), '[object Request]');
7testThrows('Request requires new', () => Request('https://example.com/'));
8
9const req0 = new Request('https://example.com/');
10test('Request method default', req0.method, 'GET');
11test('Request url', req0.url, 'https://example.com/');
12test('Request headers same object', req0.headers === req0.headers, true);
13test('Request keepalive default', req0.keepalive, false);
14test('Request duplex getter', req0.duplex, 'half');
15
16const hdrReq = new Request('https://example.com/', {
17 headers: {
18 'Accept-Charset': 'blocked',
19 'X-Custom': 'ok',
20 },
21});
22test('Request filters forbidden headers', hdrReq.headers.get('accept-charset'), null);
23test('Request keeps allowed headers', hdrReq.headers.get('x-custom'), 'ok');
24
25const noCorsReq = new Request('https://example.com/', {
26 mode: 'no-cors',
27 headers: {
28 'Content-Type': 'text/plain;charset=UTF-8',
29 'X-Blocked': 'nope',
30 },
31});
32test('Request no-cors keeps safelisted content-type', noCorsReq.headers.get('content-type'), 'text/plain;charset=UTF-8');
33test('Request no-cors strips non-safelisted header', noCorsReq.headers.get('x-blocked'), null);
34
35testThrows(
36 'Request forbids keepalive with stream body',
37 () => new Request('https://example.com/', {
38 method: 'POST',
39 body: new ReadableStream(),
40 duplex: 'half',
41 keepalive: true,
42 })
43);
44
45testThrows(
46 'Request requires duplex for stream body',
47 () => new Request('https://example.com/', {
48 method: 'POST',
49 body: new ReadableStream(),
50 })
51);
52
53testThrows(
54 'Request rejects duplex full',
55 () => new Request('https://example.com/', {
56 method: 'POST',
57 body: 'hello',
58 duplex: 'full',
59 })
60);
61
62testThrows(
63 'Request rejects forbidden method',
64 () => new Request('https://example.com/', { method: 'TRACE' })
65);
66
67testThrows(
68 'Request rejects GET with direct body',
69 () => new Request('https://example.com/', { method: 'GET', body: 'hello' })
70);
71
72const bodyReq = new Request('https://example.com/', {
73 method: 'POST',
74 body: 'hello world',
75});
76const bodyStream = bodyReq.body;
77test('Request body is a ReadableStream', bodyStream instanceof ReadableStream, true);
78test('Request body getter is stable', bodyReq.body === bodyStream, true);
79test('Request bodyUsed before consume', bodyReq.bodyUsed, false);
80test('Request text after body access', await bodyReq.text(), 'hello world');
81test('Request bodyUsed after consume', bodyReq.bodyUsed, true);
82test('Request body object preserved after consume', bodyReq.body === bodyStream, true);
83
84const srcReq = new Request('https://example.com/', {
85 method: 'POST',
86 body: 'copied body',
87});
88const srcBody = srcReq.body;
89const copiedReq = new Request(srcReq);
90test('Request-from-Request disturbs source', srcReq.bodyUsed, true);
91test('Request-from-Request keeps source body object', srcReq.body === srcBody, true);
92test('Request-from-Request creates new body object', copiedReq.body === srcBody, false);
93test('Request-from-Request text', await copiedReq.text(), 'copied body');
94
95const failReq = new Request('https://example.com/', {
96 method: 'POST',
97 body: 'will stay unused',
98});
99testThrows(
100 'Request GET from Request with body throws',
101 () => new Request(failReq, { method: 'GET' })
102);
103test('Request failed construction does not disturb source', failReq.bodyUsed, false);
104
105const usedReq = new Request('https://example.com/', {
106 method: 'POST',
107 body: 'replace me',
108});
109await usedReq.text();
110const replacedReq = new Request(usedReq, {
111 body: 'replacement body',
112 method: 'POST',
113});
114test('Request override from disturbed request succeeds', await replacedReq.text(), 'replacement body');
115
116const initReq = new Request('https://example.com/', {
117 method: 'POST',
118 body: 'init body',
119});
120const reqFromInitReq = new Request('https://example.com/', initReq);
121test('Request init from Request copies method', reqFromInitReq.method, 'POST');
122test('Request init from Request copies body', await reqFromInitReq.text(), 'init body');
123
124const emptyTypeReq = new Request('https://example.com/', {
125 method: 'POST',
126 headers: [['Content-Type', '']],
127 body: 'typed body',
128});
129const emptyTypeBlob = await emptyTypeReq.blob();
130test('Request empty content-type preserved on blob', emptyTypeBlob.type, '');
131
132summary();