1 importScripts('worker-test-harness.js');
2 importScripts('test-helpers.js');
4 var URL = 'https://www.example.com/test.html';
7 var headers = new Headers;
8 headers.set('User-Agent', 'Mozilla/5.0');
9 headers.set('Accept', 'text/html');
10 headers.set('X-ServiceWorker-Test', 'request test field');
12 var request = new Request(URL, {method: 'GET', headers: headers});
14 assert_equals(request.url, URL, 'Request.url should match');
15 assert_equals(request.method, 'GET', 'Request.method should match');
16 assert_equals(request.referrer, location.href, 'Request.referrer should match');
17 assert_true(request.headers instanceof Headers, 'Request.headers should be Headers');
19 // 'User-Agent' is a forbidden header.
20 assert_equals(request.headers.size, 2, 'Request.headers.size should match');
21 // Note: detailed behavioral tests for Headers are in another test,
22 // http/tests/serviceworker/headers.html.
24 request.url = 'http://localhost/';
25 assert_equals(request.url, 'https://www.example.com/test.html', 'Request.url should be readonly');
26 request = new Request('http://localhost/\uD800'); // Unmatched lead surrogate.
27 assert_equals(request.url,
28 'http://localhost/' + encodeURIComponent('\uFFFD'),
29 'Request.url should have unmatched surrogates replaced.');
30 request.method = 'POST';
31 assert_equals(request.method, 'GET', 'Request.method should be readonly');
32 }, 'Request basic test in ServiceWorkerGlobalScope');
36 new Request(URL, {method: ''}),
37 new Request(URL, {mode: ''}),
38 new Request(URL, {mode: 'invalid mode'}),
39 new Request(URL, {credentials: ''}),
40 new Request(URL, {credentials: 'invalid credentials'})].forEach(function(request) {
41 assert_equals(request.url, URL, 'Request.url should match');
42 assert_equals(request.method, 'GET', 'Default Request.method should be GET');
43 assert_equals(request.mode, 'cors', 'Default Request.mode should be cors');
44 assert_equals(request.credentials, 'omit', 'Default Request.credentials should be omit');
46 }, 'Request default value test in ServiceWorkerGlobalScope');
49 var request = new Request(URL);
50 request.headers.append('X-ServiceWorker-Foo', 'foo1');
51 request.headers.append('X-ServiceWorker-Foo', 'foo2');
52 request.headers.append('X-ServiceWorker-Bar', 'bar');
53 var request2 = new Request(request);
54 assert_equals(request2.url, URL, 'Request.url should match');
55 assert_equals(request2.method, 'GET', 'Request.method should match');
56 assert_equals(request2.mode, 'cors', 'Request.mode should match');
57 assert_equals(request2.credentials, 'omit', 'Request.credentials should match');
58 assert_equals(request2.headers.getAll('X-ServiceWorker-Foo')[0], 'foo1',
59 'Request.headers should match');
60 assert_equals(request2.headers.getAll('X-ServiceWorker-Foo')[1], 'foo2',
61 'Request.headers should match');
62 assert_equals(request2.headers.getAll('X-ServiceWorker-Bar')[0], 'bar',
63 'Request.headers should match');
64 }, 'Request header test in ServiceWorkerGlobalScope');
69 var METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'OPTIONS', '', undefined];
70 var MODES = ['same-origin', 'no-cors', 'cors', '', undefined];
71 function isSimpleMethod(method) {
72 return ['GET', 'HEAD', 'POST', '', undefined].indexOf(method) != -1;
74 function effectiveMethod(method1, method2) {
75 return method2 ? method2 : (method1 ? method1 : 'GET');
77 function effectiveMode(mode1, mode2) {
78 return mode2 ? mode2 : (mode1 ? mode1 : 'cors');
80 METHODS.forEach(function(method1) {
81 MODES.forEach(function(mode1) {
83 if (method1 != undefined) { init1['method'] = method1; }
84 if (mode1 != undefined) { init1['mode'] = mode1; }
85 if (!isSimpleMethod(method1) && mode1 == 'no-cors') {
88 function() { request1 = new Request(URL, init1); },
89 'new no-cors Request with non simple method (' + method1 +') should throw');
92 request1 = new Request(URL, init1);
93 assert_equals(request1.method, method1 ? method1 : 'GET', 'Request.method should match');
94 assert_equals(request1.mode, mode1 ? mode1 : 'cors', 'Request.mode should match');
95 request1 = new Request(request1);
96 assert_equals(request1.method, method1 ? method1 : 'GET', 'Request.method should match');
97 assert_equals(request1.mode, mode1 ? mode1 : 'cors', 'Request.mode should match');
98 METHODS.forEach(function(method2) {
99 MODES.forEach(function(mode2) {
100 // We need to construct a new request1 because as soon as it
101 // is used in a constructor it will be flagged as 'used',
102 // and we can no longer construct objects with it.
103 request1 = new Request(URL, init1);
105 if (method2 != undefined) { init2['method'] = method2; }
106 if (mode2 != undefined) { init2['mode'] = mode2; }
107 if (!isSimpleMethod(effectiveMethod(method1, method2)) && effectiveMode(mode1, mode2) == 'no-cors') {
110 function() { request2 = new Request(request1, init2); },
111 'new no-cors Request with non simple method should throw');
114 request2 = new Request(request1, init2);
115 assert_equals(request2.method,
116 method2 ? method2 : request1.method,
117 'Request.method should be overridden');
118 assert_equals(request2.mode,
119 mode2 ? mode2 : request1.mode,
120 'Request.mode should be overridden');
125 }, 'Request header test in ServiceWorkerGlobalScope');
130 var CREDENTIALS = ['omit', 'same-origin', 'include', '', undefined];
131 CREDENTIALS.forEach(function(credentials1) {
133 if (credentials1 != undefined) { init1['credentials'] = credentials1; }
134 request1 = new Request(URL, init1);
135 assert_equals(request1.credentials, credentials1 ? credentials1 : 'omit', 'Request.credentials should match');
136 request1 = new Request(request1);
137 assert_equals(request1.credentials, credentials1 ? credentials1 : 'omit', 'Request.credentials should match');
138 CREDENTIALS.forEach(function(credentials2) {
139 request1 = new Request(URL, init1);
141 if (credentials2 != undefined) { init2['credentials'] = credentials2; }
142 request2 = new Request(request1, init2);
143 assert_equals(request2.credentials,
144 credentials2 ? credentials2 : request1.credentials,
145 'Request.credentials should be overridden');
148 }, 'Request credentials test in ServiceWorkerGlobalScope');
151 ['same-origin', 'cors', 'no-cors'].forEach(function(mode) {
152 var forbiddenMethods = ['TRACE', 'TRACK', 'CONNECT'];
153 forbiddenMethods.forEach(function(method) {
156 function() { var request = new Request(URL, {mode: mode, method: method}); },
157 'new Request with a forbidden method (' + method +') should throw');
159 var invalidNames = ['(', ')', '<', '>', '@', ',', ';', ':', '\\', '"',
160 '/', '[', ']', '?', '=', '{', '}', '\u3042', 'a(b',
162 invalidNames.forEach(function(name) {
165 function() { var request = new Request(URL, {mode: mode, method: name}); },
166 'new Request with an invalid method (' + name +') should throw');
169 }, 'Request method name test in ServiceWorkerGlobalScope');
172 var FORBIDDEN_HEADERS =
173 ['Accept-Charset', 'Accept-Encoding', 'Access-Control-Request-Headers',
174 'Access-Control-Request-Method', 'Connection', 'Content-Length', 'Cookie',
175 'Cookie2', 'Date', 'DNT', 'Expect', 'Host', 'Keep-Alive', 'Origin',
176 'Referer', 'TE', 'Trailer', 'Transfer-Encoding', 'Upgrade', 'User-Agent',
177 'Via', 'Proxy-', 'Sec-', 'Proxy-FooBar', 'Sec-FooBar'];
179 [['Accept', '*'], ['Accept-Language', 'ru'], ['Content-Language', 'ru'],
180 ['Content-Type', 'application/x-www-form-urlencoded'],
181 ['Content-Type', 'multipart/form-data'],
182 ['Content-Type', 'text/plain']];
183 var NON_SIMPLE_HEADERS =
184 [['X-ServiceWorker-Test', 'test'],
185 ['X-ServiceWorker-Test2', 'test2'],
186 ['Content-Type', 'foo/bar']];
188 ['same-origin', 'cors'].forEach(function(mode) {
189 var request = new Request(URL, {mode: mode});
190 FORBIDDEN_HEADERS.forEach(function(header) {
191 request.headers.append(header, 'test');
192 assert_equals(request.headers.size, 0,
193 'Request.headers.append should ignore the forbidden headers');
194 request.headers.set(header, 'test');
195 assert_equals(request.headers.size, 0,
196 'Request.headers.set should ignore the forbidden headers');
198 var request = new Request(URL, {mode: mode});
199 assert_equals(request.headers.size, 0);
200 NON_SIMPLE_HEADERS.forEach(function(header) {
201 request.headers.append(header[0], header[1]);
203 assert_equals(request.headers.size, NON_SIMPLE_HEADERS.length);
204 NON_SIMPLE_HEADERS.forEach(function(header) {
205 assert_equals(request.headers.get(header[0]), header[1]);
207 request = new Request(URL, {mode: mode});
208 assert_equals(request.headers.size, 0);
209 NON_SIMPLE_HEADERS.forEach(function(header) {
210 request.headers.set(header[0], header[1]);
212 assert_equals(request.headers.size, NON_SIMPLE_HEADERS.length);
213 NON_SIMPLE_HEADERS.forEach(function(header) {
214 assert_equals(request.headers.get(header[0]), header[1]);
217 request = new Request(URL, {mode: 'no-cors'});
218 FORBIDDEN_HEADERS.forEach(function(header) {
219 request.headers.set(header, 'test');
220 request.headers.append(header, 'test');
222 NON_SIMPLE_HEADERS.forEach(function(header) {
223 request.headers.set(header[0], header[1]);
224 request.headers.append(header[0], header[1]);
226 assert_equals(request.headers.size, 0,
227 'no-cors request should only accept simple headers');
229 SIMPLE_HEADERS.forEach(function(header) {
230 request = new Request(URL, {mode: 'no-cors'});
231 request.headers.append(header[0], header[1]);
232 assert_equals(request.headers.size, 1,
233 'no-cors request should accept simple headers');
234 request = new Request(URL, {mode: 'no-cors'});
235 request.headers.set(header[0], header[1]);
236 assert_equals(request.headers.size, 1,
237 'no-cors request should accept simple headers');
238 request.headers.delete(header[0]);
239 if (header[0] == 'Content-Type') {
241 request.headers.size, 1,
242 'Content-Type header of no-cors request shouldn\'t be deleted');
244 assert_equals(request.headers.size, 0);
248 SIMPLE_HEADERS.forEach(function(header) {
250 NON_SIMPLE_HEADERS.forEach(function(header2) {
251 headers[header2[0]] = header2[1];
253 FORBIDDEN_HEADERS.forEach(function(header) { headers[header] = 'foo'; });
254 headers[header[0]] = header[1];
255 var expectedSize = NON_SIMPLE_HEADERS.length;
256 if (header[0] != 'Content-Type') {
259 ['same-origin', 'cors'].forEach(function(mode) {
260 request = new Request(URL, {mode: mode, headers: headers});
261 assert_equals(request.headers.size, expectedSize,
262 'Request should not support the forbidden headers');
264 request = new Request(URL, {mode: 'no-cors', headers: headers});
265 assert_equals(request.headers.size, 1,
266 'No-CORS Request.headers should only support simple headers');
267 ['same-origin', 'cors', 'no-cors'].forEach(function(mode) {
268 request = new Request(new Request(URL, {mode: mode, headers: headers}), {mode: 'no-cors'});
269 assert_equals(request.headers.size, 1,
270 'No-CORS Request.headers should only support simple headers');
273 }, 'Request headers test in ServiceWorkerGlobalScope');
276 var url = 'http://example.com';
277 ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'].forEach(function(method) {
278 assert_equals(new Request(url, {method: method.toLowerCase()}).method,
280 'method should be normalized to uppercase: ' + method);
283 ['PATCH', 'MKCOL', 'CUSTOM', 'X-FILES'].forEach(function(method) {
284 assert_equals(new Request(url, {method: method}).method, method,
285 'method should not be changed when normalized: ' + method);
286 method = method.toLowerCase();
287 assert_equals(new Request(url, {method: method}).method, method,
288 'method should not be changed when normalized: ' + method);
290 }, 'Request method names are normalized');
293 var req = new Request(URL);
294 assert_false(req.bodyUsed,
295 "Request should not be flagged as used if it has not been consumed.");
296 var req2 = new Request(req);
297 assert_true(req.bodyUsed,
298 "Request should be flagged as used if it is used as a construction " +
299 "argument of another Request.");
300 assert_false(req2.bodyUsed,
301 "Request should not be flagged as used if it has not been consumed.");
302 assert_throws(new TypeError(), function() { new Request(req); },
303 "Request cannot be constructed with a request that has been flagged as used.");
304 }, 'Request construction behavior regarding "used" body flag and exceptions.');
306 promise_test(function() {
307 var headers = new Headers;
308 headers.set('Content-Language', 'ja');
309 var req = new Request(URL, {
312 body: new Blob(['Test Blob'], {type: 'test/type'})
314 var req2 = req.clone();
315 // Change headers and of original request.
316 req.headers.set('Content-Language', 'en');
318 req2.headers.get('Content-Language'), 'ja', 'Headers of cloned request ' +
319 'should not change when original request headers are changed.');
322 .then(function(text) {
323 assert_equals(text, 'Test Blob', 'Body of request should match.');
326 .then(function(text) {
327 assert_equals(text, 'Test Blob', 'Cloned request body should match.');
329 }, 'Test clone behavior with loading content from Request.');
331 async_test(function(t) {
332 var getContentType = function(headers) {
333 var content_type = '';
334 headers.forEach(function(value, key) {
335 if (key == 'content-type') {
336 content_type = value;
345 body: new Blob(['Test Blob'], {type: 'test/type'})
348 getContentType(request.headers), 'test/type',
349 'ContentType header of Request created with Blob body must be set.');
350 assert_false(request.bodyUsed,
351 'bodyUsed must be true before calling text()');
353 .then(function(result) {
354 assert_equals(result, 'Test Blob',
355 'Creating a Request with Blob body should success.');
357 request = new Request(URL, {method: 'POST', body: 'Test String'});
359 getContentType(request.headers), 'text/plain;charset=UTF-8',
360 'ContentType header of Request created with string must be set.');
361 return request.text();
363 .then(function(result) {
364 assert_equals(result, 'Test String',
365 'Creating a Request with string body should success.');
367 var text = "Test ArrayBuffer";
368 var array = new Uint8Array(text.length);
369 for (var i = 0; i < text.length; ++i)
370 array[i] = text.charCodeAt(i);
371 request = new Request(URL, {method: 'POST', body: array.buffer});
372 return request.text();
374 .then(function(result) {
376 result, 'Test ArrayBuffer',
377 'Creating a Request with ArrayBuffer body should success.');
379 var text = "Test ArrayBufferView";
380 var array = new Uint8Array(text.length);
381 for (var i = 0; i < text.length; ++i)
382 array[i] = text.charCodeAt(i);
383 request = new Request(URL, {method: 'POST', body: array});
384 return request.text();
386 .then(function(result) {
388 result, 'Test ArrayBufferView',
389 'Creating a Request with ArrayBuffer body should success.');
391 var formData = new FormData();
392 formData.append('sample string', '1234567890');
393 formData.append('sample blob', new Blob(['blob content']));
394 formData.append('sample file',
395 new File(['file content'], 'file.dat'));
396 request = new Request(URL, {method: 'POST', body: formData});
397 return request.text();
399 .then(function(result) {
400 var reg = new RegExp('multipart\/form-data; boundary=(.*)');
401 var regResult = reg.exec(getContentType(request.headers));
402 var boundary = regResult[1];
404 '--' + boundary + '\r\n' +
405 'Content-Disposition: form-data; name="sample string"\r\n' +
408 '--' + boundary + '\r\n' +
409 'Content-Disposition: form-data; name="sample blob"; ' +
410 'filename="blob"\r\n' +
411 'Content-Type: application/octet-stream\r\n' +
414 '--' + boundary + '\r\n' +
415 'Content-Disposition: form-data; name="sample file"; ' +
416 'filename="file.dat"\r\n' +
417 'Content-Type: application/octet-stream\r\n' +
420 '--' + boundary + '--\r\n';
422 result, expected_body,
423 'Creating a Request with FormData body should success.');
428 .catch(unreached_rejection(t));
429 assert_true(request.bodyUsed,
430 'bodyUsed must be true after calling text()');
431 }, 'Request body test in ServiceWorkerGlobalScope');