cache-put.https.any.js (16193B)
1 // META: title=Cache.put 2 // META: global=window,worker 3 // META: script=/common/get-host-info.sub.js 4 // META: script=./resources/test-helpers.js 5 // META: timeout=long 6 7 var test_url = 'https://example.com/foo'; 8 var test_body = 'Hello world!'; 9 const { REMOTE_HOST } = get_host_info(); 10 11 cache_test(function(cache) { 12 var request = new Request(test_url); 13 var response = new Response(test_body); 14 return cache.put(request, response) 15 .then(function(result) { 16 assert_equals(result, undefined, 17 'Cache.put should resolve with undefined on success.'); 18 }); 19 }, 'Cache.put called with simple Request and Response'); 20 21 cache_test(function(cache) { 22 var test_url = new URL('./resources/simple.txt', location.href).href; 23 var request = new Request(test_url); 24 var response; 25 return fetch(test_url) 26 .then(function(fetch_result) { 27 response = fetch_result.clone(); 28 return cache.put(request, fetch_result); 29 }) 30 .then(function() { 31 return cache.match(test_url); 32 }) 33 .then(function(result) { 34 assert_response_equals(result, response, 35 'Cache.put should update the cache with ' + 36 'new request and response.'); 37 return result.text(); 38 }) 39 .then(function(body) { 40 assert_equals(body, 'a simple text file\n', 41 'Cache.put should store response body.'); 42 }); 43 }, 'Cache.put called with Request and Response from fetch()'); 44 45 cache_test(function(cache) { 46 var request = new Request(test_url); 47 var response = new Response(test_body); 48 assert_false(request.bodyUsed, 49 '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + 50 'Request.bodyUsed should be initially false.'); 51 return cache.put(request, response) 52 .then(function() { 53 assert_false(request.bodyUsed, 54 'Cache.put should not mark empty request\'s body used'); 55 }); 56 }, 'Cache.put with Request without a body'); 57 58 cache_test(function(cache) { 59 var request = new Request(test_url); 60 var response = new Response(); 61 assert_false(response.bodyUsed, 62 '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + 63 'Response.bodyUsed should be initially false.'); 64 return cache.put(request, response) 65 .then(function() { 66 assert_false(response.bodyUsed, 67 'Cache.put should not mark empty response\'s body used'); 68 }); 69 }, 'Cache.put with Response without a body'); 70 71 cache_test(function(cache) { 72 var request = new Request(test_url); 73 var response = new Response(test_body); 74 return cache.put(request, response.clone()) 75 .then(function() { 76 return cache.match(test_url); 77 }) 78 .then(function(result) { 79 assert_response_equals(result, response, 80 'Cache.put should update the cache with ' + 81 'new Request and Response.'); 82 }); 83 }, 'Cache.put with a Response containing an empty URL'); 84 85 cache_test(function(cache) { 86 var request = new Request(test_url); 87 var response = new Response('', { 88 status: 200, 89 headers: [['Content-Type', 'text/plain']] 90 }); 91 return cache.put(request, response) 92 .then(function() { 93 return cache.match(test_url); 94 }) 95 .then(function(result) { 96 assert_equals(result.status, 200, 'Cache.put should store status.'); 97 assert_equals(result.headers.get('Content-Type'), 'text/plain', 98 'Cache.put should store headers.'); 99 return result.text(); 100 }) 101 .then(function(body) { 102 assert_equals(body, '', 103 'Cache.put should store response body.'); 104 }); 105 }, 'Cache.put with an empty response body'); 106 107 cache_test(function(cache, test) { 108 var request = new Request(test_url); 109 var response = new Response('', { 110 status: 206, 111 headers: [['Content-Type', 'text/plain']] 112 }); 113 114 return promise_rejects_js( 115 test, 116 TypeError, 117 cache.put(request, response), 118 'Cache.put should reject 206 Responses with a TypeError.'); 119 }, 'Cache.put with synthetic 206 response'); 120 121 cache_test(function(cache, test) { 122 var test_url = new URL('./resources/fetch-status.py?status=206', location.href).href; 123 var request = new Request(test_url); 124 var response; 125 return fetch(test_url) 126 .then(function(fetch_result) { 127 assert_equals(fetch_result.status, 206, 128 'Test framework error: The status code should be 206.'); 129 response = fetch_result.clone(); 130 return promise_rejects_js(test, TypeError, cache.put(request, fetch_result)); 131 }); 132 }, 'Cache.put with HTTP 206 response'); 133 134 cache_test(function(cache, test) { 135 // We need to jump through some hoops to allow the test to perform opaque 136 // response filtering, but bypass the ORB safelist check. This is 137 // done, by forcing the MIME type retrieval to fail and the 138 // validation of partial first response to succeed. 139 var pipe = "status(206)|header(Content-Type,)|header(Content-Range, bytes 0-1/41)|slice(null, 1)"; 140 var test_url = new URL(`./resources/blank.html?pipe=${pipe}`, location.href); 141 test_url.hostname = REMOTE_HOST; 142 var request = new Request(test_url.href, { mode: 'no-cors' }); 143 var response; 144 return fetch(request) 145 .then(function(fetch_result) { 146 assert_equals(fetch_result.type, 'opaque', 147 'Test framework error: The response type should be opaque.'); 148 assert_equals(fetch_result.status, 0, 149 'Test framework error: The status code should be 0 for an ' + 150 ' opaque-filtered response. This is actually HTTP 206.'); 151 response = fetch_result.clone(); 152 return cache.put(request, fetch_result); 153 }) 154 .then(function() { 155 return cache.match(test_url); 156 }) 157 .then(function(result) { 158 assert_not_equals(result, undefined, 159 'Cache.put should store an entry for the opaque response'); 160 }); 161 }, 'Cache.put with opaque-filtered HTTP 206 response'); 162 163 cache_test(function(cache) { 164 var test_url = new URL('./resources/fetch-status.py?status=500', location.href).href; 165 var request = new Request(test_url); 166 var response; 167 return fetch(test_url) 168 .then(function(fetch_result) { 169 assert_equals(fetch_result.status, 500, 170 'Test framework error: The status code should be 500.'); 171 response = fetch_result.clone(); 172 return cache.put(request, fetch_result); 173 }) 174 .then(function() { 175 return cache.match(test_url); 176 }) 177 .then(function(result) { 178 assert_response_equals(result, response, 179 'Cache.put should update the cache with ' + 180 'new request and response.'); 181 return result.text(); 182 }) 183 .then(function(body) { 184 assert_equals(body, '', 185 'Cache.put should store response body.'); 186 }); 187 }, 'Cache.put with HTTP 500 response'); 188 189 cache_test(function(cache) { 190 var alternate_response_body = 'New body'; 191 var alternate_response = new Response(alternate_response_body, 192 { statusText: 'New status' }); 193 return cache.put(new Request(test_url), 194 new Response('Old body', { statusText: 'Old status' })) 195 .then(function() { 196 return cache.put(new Request(test_url), alternate_response.clone()); 197 }) 198 .then(function() { 199 return cache.match(test_url); 200 }) 201 .then(function(result) { 202 assert_response_equals(result, alternate_response, 203 'Cache.put should replace existing ' + 204 'response with new response.'); 205 return result.text(); 206 }) 207 .then(function(body) { 208 assert_equals(body, alternate_response_body, 209 'Cache put should store new response body.'); 210 }); 211 }, 'Cache.put called twice with matching Requests and different Responses'); 212 213 cache_test(function(cache) { 214 var first_url = test_url; 215 var second_url = first_url + '#(O_o)'; 216 var third_url = first_url + '#fragment'; 217 var alternate_response_body = 'New body'; 218 var alternate_response = new Response(alternate_response_body, 219 { statusText: 'New status' }); 220 return cache.put(new Request(first_url), 221 new Response('Old body', { statusText: 'Old status' })) 222 .then(function() { 223 return cache.put(new Request(second_url), alternate_response.clone()); 224 }) 225 .then(function() { 226 return cache.match(test_url); 227 }) 228 .then(function(result) { 229 assert_response_equals(result, alternate_response, 230 'Cache.put should replace existing ' + 231 'response with new response.'); 232 return result.text(); 233 }) 234 .then(function(body) { 235 assert_equals(body, alternate_response_body, 236 'Cache put should store new response body.'); 237 }) 238 .then(function() { 239 return cache.put(new Request(third_url), alternate_response.clone()); 240 }) 241 .then(function() { 242 return cache.keys(); 243 }) 244 .then(function(results) { 245 // Should match urls (without fragments or with different ones) to the 246 // same cache key. However, result.url should be the latest url used. 247 assert_equals(results[0].url, third_url); 248 return; 249 }); 250 }, 'Cache.put called multiple times with request URLs that differ only by a fragment'); 251 252 cache_test(function(cache) { 253 var url = 'http://example.com/foo'; 254 return cache.put(url, new Response('some body')) 255 .then(function() { return cache.match(url); }) 256 .then(function(response) { return response.text(); }) 257 .then(function(body) { 258 assert_equals(body, 'some body', 259 'Cache.put should accept a string as request.'); 260 }); 261 }, 'Cache.put with a string request'); 262 263 cache_test(function(cache, test) { 264 return promise_rejects_js( 265 test, 266 TypeError, 267 cache.put(new Request(test_url), 'Hello world!'), 268 'Cache.put should only accept a Response object as the response.'); 269 }, 'Cache.put with an invalid response'); 270 271 cache_test(function(cache, test) { 272 return promise_rejects_js( 273 test, 274 TypeError, 275 cache.put(new Request('file:///etc/passwd'), 276 new Response(test_body)), 277 'Cache.put should reject non-HTTP/HTTPS requests with a TypeError.'); 278 }, 'Cache.put with a non-HTTP/HTTPS request'); 279 280 cache_test(function(cache) { 281 var response = new Response(test_body); 282 return cache.put(new Request('relative-url'), response.clone()) 283 .then(function() { 284 return cache.match(new URL('relative-url', location.href).href); 285 }) 286 .then(function(result) { 287 assert_response_equals(result, response, 288 'Cache.put should accept a relative URL ' + 289 'as the request.'); 290 }); 291 }, 'Cache.put with a relative URL'); 292 293 cache_test(function(cache, test) { 294 var request = new Request('http://example.com/foo', { method: 'HEAD' }); 295 return promise_rejects_js( 296 test, 297 TypeError, 298 cache.put(request, new Response(test_body)), 299 'Cache.put should throw a TypeError for non-GET requests.'); 300 }, 'Cache.put with a non-GET request'); 301 302 cache_test(function(cache, test) { 303 return promise_rejects_js( 304 test, 305 TypeError, 306 cache.put(new Request(test_url), null), 307 'Cache.put should throw a TypeError for a null response.'); 308 }, 'Cache.put with a null response'); 309 310 cache_test(function(cache, test) { 311 var request = new Request(test_url, {method: 'POST', body: test_body}); 312 return promise_rejects_js( 313 test, 314 TypeError, 315 cache.put(request, new Response(test_body)), 316 'Cache.put should throw a TypeError for a POST request.'); 317 }, 'Cache.put with a POST request'); 318 319 cache_test(function(cache) { 320 var response = new Response(test_body); 321 assert_false(response.bodyUsed, 322 '[https://fetch.spec.whatwg.org/#dom-body-bodyused] ' + 323 'Response.bodyUsed should be initially false.'); 324 return response.text().then(function() { 325 assert_true( 326 response.bodyUsed, 327 '[https://fetch.spec.whatwg.org/#concept-body-consume-body] ' + 328 'The text() method should make the body disturbed.'); 329 var request = new Request(test_url); 330 return cache.put(request, response).then(() => { 331 assert_unreached('cache.put should be rejected'); 332 }, () => {}); 333 }); 334 }, 'Cache.put with a used response body'); 335 336 cache_test(function(cache) { 337 var response = new Response(test_body); 338 return cache.put(new Request(test_url), response) 339 .then(function() { 340 assert_throws_js(TypeError, () => response.body.getReader()); 341 }); 342 }, 'getReader() after Cache.put'); 343 344 cache_test(function(cache, test) { 345 return promise_rejects_js( 346 test, 347 TypeError, 348 cache.put(new Request(test_url), 349 new Response(test_body, { headers: { VARY: '*' }})), 350 'Cache.put should reject VARY:* Responses with a TypeError.'); 351 }, 'Cache.put with a VARY:* Response'); 352 353 cache_test(function(cache, test) { 354 return promise_rejects_js( 355 test, 356 TypeError, 357 cache.put(new Request(test_url), 358 new Response(test_body, 359 { headers: { VARY: 'Accept-Language,*' }})), 360 'Cache.put should reject Responses with an embedded VARY:* with a ' + 361 'TypeError.'); 362 }, 'Cache.put with an embedded VARY:* Response'); 363 364 cache_test(async function(cache, test) { 365 const url = new URL('./resources/vary.py?vary=*', 366 get_host_info().HTTPS_REMOTE_ORIGIN + self.location.pathname); 367 const request = new Request(url, { mode: 'no-cors' }); 368 const response = await fetch(request); 369 assert_equals(response.type, 'opaque'); 370 await cache.put(request, response); 371 }, 'Cache.put with a VARY:* opaque response should not reject'); 372 373 cache_test(function(cache) { 374 var url = 'foo.html'; 375 var redirectURL = 'http://example.com/foo-bar.html'; 376 var redirectResponse = Response.redirect(redirectURL); 377 assert_equals(redirectResponse.headers.get('Location'), redirectURL, 378 'Response.redirect() should set Location header.'); 379 return cache.put(url, redirectResponse.clone()) 380 .then(function() { 381 return cache.match(url); 382 }) 383 .then(function(response) { 384 assert_response_equals(response, redirectResponse, 385 'Redirect response is reproduced by the Cache API'); 386 assert_equals(response.headers.get('Location'), redirectURL, 387 'Location header is preserved by Cache API.'); 388 }); 389 }, 'Cache.put should store Response.redirect() correctly'); 390 391 cache_test(async (cache) => { 392 var request = new Request(test_url); 393 var response = new Response(new Blob([test_body])); 394 await cache.put(request, response); 395 var cachedResponse = await cache.match(request); 396 assert_equals(await cachedResponse.text(), test_body); 397 }, 'Cache.put called with simple Request and blob Response'); 398 399 cache_test(async (cache) => { 400 var formData = new FormData(); 401 formData.append("name", "value"); 402 403 var request = new Request(test_url); 404 var response = new Response(formData); 405 await cache.put(request, response); 406 var cachedResponse = await cache.match(request); 407 var cachedResponseText = await cachedResponse.text(); 408 assert_true(cachedResponseText.indexOf("name=\"name\"\r\n\r\nvalue") !== -1); 409 }, 'Cache.put called with simple Request and form data Response'); 410 411 done();