Skip to content

Commit bb4cd6f

Browse files
committed
Bug 1688827 [wpt PR 27325] - Test cases where request body gets used before network fallback, a=testonly
Automatic update from web-platform-tests Test cases where request body gets used before network fallback (#27325) Tests for whatwg/fetch#1144 and w3c/ServiceWorker#1563. Co-authored-by: Yutaka Hirano <yhiranochrmomium.org> Co-authored-by: Anne van Kesteren <annevkannevk.nl> -- wpt-commits: c30545df6a50c61f3673ed952c78c0a607100d45 wpt-pr: 27325 UltraBlame original commit: fc2a98935821f5df9bf73b8642ff68ab95e1ea17
1 parent 45b269e commit bb4cd6f

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed

testing/web-platform/tests/service-workers/service-worker/fetch-event.https.html

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,137 @@
480480
});
481481
}, 'FetchEvent#body is a string and is passed to network fallback');
482482

483+
// Test that the request body is sent to network upon network fallback,
484+
// for a ReadableStream body.
485+
promise_test(async t => {
486+
const rs = new ReadableStream({start(c) {
487+
c.enqueue('i a');
488+
c.enqueue('m the request');
489+
t.step_timeout(t.step_func(() => {
490+
c.enqueue(' body');
491+
c.close();
492+
}, 10));
493+
}});
494+
// Set page_url to "?ignore" so the service worker falls back to network
495+
// for the main resource request, and add a suffix to avoid colliding
496+
// with other tests.
497+
const page_url = 'resources/?ignore-for-request-body-fallback-string';
498+
const frame = await with_iframe(page_url);
499+
t.add_cleanup(() => { frame.remove(); });
500+
// Add "?ignore" so the service worker falls back to echo-content.py.
501+
const echo_url = '/fetch/api/resources/echo-content.py?ignore';
502+
const response = await frame.contentWindow.fetch(echo_url, {
503+
method: 'POST',
504+
body: rs
505+
});
506+
const text = await response.text();
507+
assert_equals(text,
508+
'i am the request body',
509+
'the network fallback request should include the request body');
510+
}, 'FetchEvent#body is a ReadableStream and is passed to network fallback');
511+
512+
// Test that the request body is sent to network upon network fallback even when
513+
// the request body is used in the service worker, for a string body.
514+
promise_test(async t => {
515+
// Set page_url to "?ignore" so the service worker falls back to network
516+
// for the main resource request, and add a suffix to avoid colliding
517+
// with other tests.
518+
const page_url = 'resources/?ignore-for-request-body-fallback-string';
519+
520+
const frame = await with_iframe(page_url);
521+
t.add_cleanup(() => { frame.remove(); });
522+
// Add "?use-and-ignore" so the service worker falls back to echo-content.py.
523+
const echo_url = '/fetch/api/resources/echo-content.py?use-and-ignore';
524+
const response = await frame.contentWindow.fetch(echo_url, {
525+
method: 'POST',
526+
body: 'i am the request body'
527+
});
528+
const text = await response.text();
529+
assert_equals(
530+
text,
531+
'i am the request body',
532+
'the network fallback request should include the request body');
533+
}, 'FetchEvent#body is a string, used and passed to network fallback');
534+
535+
// When the streaming body is used in the service worker, network fallback
536+
// fails.
537+
promise_test(async t => {
538+
const rs = new ReadableStream({start(c) {
539+
c.enqueue('i a');
540+
c.enqueue('m the request');
541+
t.step_timeout(t.step_func(() => {
542+
c.enqueue(' body');
543+
c.close();
544+
}, 10));
545+
}});
546+
// Set page_url to "?ignore" so the service worker falls back to network
547+
// for the main resource request, and add a suffix to avoid colliding
548+
// with other tests.
549+
const page_url = 'resources/?ignore-for-request-body-fallback-string';
550+
const frame = await with_iframe(page_url);
551+
t.add_cleanup(() => { frame.remove(); });
552+
const echo_url = '/fetch/api/resources/echo-content.py?use-and-ignore';
553+
await promise_rejects_js(t, TypeError, frame.contentWindow.fetch(echo_url, {
554+
method: 'POST',
555+
body: rs
556+
});
557+
}, 'FetchEvent#body is a ReadableStream, used and passed to network fallback');
558+
559+
// Test that the request body is sent to network upon network fallback even when
560+
// the request body is used by clone() in the service worker, for a string body.
561+
promise_test(async t => {
562+
// Set page_url to "?ignore" so the service worker falls back to network
563+
// for the main resource request, and add a suffix to avoid colliding
564+
// with other tests.
565+
const page_url = 'resources/?ignore-for-request-body-fallback-string';
566+
567+
const frame = await with_iframe(page_url);
568+
t.add_cleanup(() => { frame.remove(); });
569+
// Add "?clone-and-ignore" so the service worker falls back to
570+
// echo-content.py.
571+
const echo_url = '/fetch/api/resources/echo-content.py?clone-and-ignore';
572+
const response = await frame.contentWindow.fetch(echo_url, {
573+
method: 'POST',
574+
body: 'i am the request body'
575+
});
576+
const text = await response.text();
577+
assert_equals(
578+
text,
579+
'i am the request body',
580+
'the network fallback request should include the request body');
581+
}, 'FetchEvent#body is a string, cloned and passed to network fallback');
582+
583+
// When the streaming body is used by clone() in the service worker, network
584+
// fallback fails.
585+
promise_test(async t => {
586+
const rs = new ReadableStream({start(c) {
587+
c.enqueue('i a');
588+
c.enqueue('m the request');
589+
t.step_timeout(t.step_func(() => {
590+
c.enqueue(' body');
591+
c.close();
592+
}, 10));
593+
}});
594+
// Set page_url to "?ignore" so the service worker falls back to network
595+
// for the main resource request, and add a suffix to avoid colliding
596+
// with other tests.
597+
const page_url = 'resources/?ignore-for-request-body-fallback-string';
598+
const frame = await with_iframe(page_url);
599+
t.add_cleanup(() => { frame.remove(); });
600+
// Add "?clone-and-ignore" so the service worker falls back to
601+
// echo-content.py.
602+
const echo_url = '/fetch/api/resources/echo-content.py?clone-and-ignore';
603+
const response = await frame.contentWindow.fetch(echo_url, {
604+
method: 'POST',
605+
body: 'i am the request body'
606+
});
607+
const text = await response.text();
608+
assert_equals(
609+
text,
610+
'i am the request body',
611+
'the network fallback request should include the request body');
612+
}, 'FetchEvent#body is a ReadableStream, cloned and passed to network fallback');
613+
483614
// Test that the service worker can read FetchEvent#body when it is a blob.
484615
// It responds with request body it read.
485616
promise_test(t => {
@@ -851,5 +982,52 @@
851982
assert_equals(frame.contentDocument.body.textContent,
852983
'method = POST, isHistoryNavigation = true');
853984
}, 'FetchEvent#request.isHistoryNavigation is true (POST + history.go(-1))');
985+
986+
// When service worker responds with a Response, no XHR upload progress
987+
// events are delivered.
988+
promise_test(async t => {
989+
const page_url = 'resources/simple.html?ignore-for-request-body-string';
990+
const frame = await with_iframe(page_url);
991+
t.add_cleanup(() => { frame.remove(); });
992+
993+
const xhr = new frame.contentWindow.XMLHttpRequest();
994+
xhr.open('POST', 'simple.html?request-body');
995+
xhr.upload.addEventListener('progress', t.unreached_func('progress'));
996+
xhr.upload.addEventListener('error', t.unreached_func('error'));
997+
xhr.upload.addEventListener('abort', t.unreached_func('abort'));
998+
xhr.upload.addEventListener('timeout', t.unreached_func('timeout'));
999+
xhr.upload.addEventListener('load', t.unreached_func('load'));
1000+
xhr.upload.addEventListener('loadend', t.unreached_func('loadend'));
1001+
xhr.send('i am the request body');
1002+
1003+
await new Promise((resolve) => xhr.addEventListener('load', resolve));
1004+
}, 'XHR upload progress events for response coming from SW');
1005+
1006+
// Upload progress events should be delivered for the network fallback case.
1007+
promise_test(async t => {
1008+
const page_url = 'resources/simple.html?ignore-for-request-body-string';
1009+
const frame = await with_iframe(page_url);
1010+
t.add_cleanup(() => { frame.remove(); });
1011+
1012+
let progress = false;
1013+
let load = false;
1014+
let loadend = false;
1015+
1016+
const xhr = new frame.contentWindow.XMLHttpRequest();
1017+
xhr.open('POST', '/fetch/api/resources/echo-content.py?ignore');
1018+
xhr.upload.addEventListener('progress', () => progress = true);
1019+
xhr.upload.addEventListener('error', t.unreached_func('error'));
1020+
xhr.upload.addEventListener('abort', t.unreached_func('abort'));
1021+
xhr.upload.addEventListener('timeout', t.unreached_func('timeout'));
1022+
xhr.upload.addEventListener('load', () => load = true);
1023+
xhr.upload.addEventListener('loadend', () => loadend = true);
1024+
xhr.send('i am the request body');
1025+
1026+
await new Promise((resolve) => xhr.addEventListener('load', resolve));
1027+
assert_true(progress, 'progress');
1028+
assert_true(load, 'load');
1029+
assert_true(loadend, 'loadend');
1030+
}, 'XHR upload progress events for network fallback');
1031+
8541032
</script>
8551033
</body>

testing/web-platform/tests/service-workers/service-worker/resources/fetch-event-test-worker.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ function handleIsHistoryNavigation(event) {
155155
event.respondWith(new Response(body));
156156
}
157157

158+
function handleUseAndIgnore(event) {
159+
const request = event.request;
160+
request.text();
161+
return;
162+
}
163+
164+
function handleCloneAndIgnore(event) {
165+
const request = event.request;
166+
request.clone().text();
167+
return;
168+
}
169+
158170
self.addEventListener('fetch', function(event) {
159171
var url = event.request.url;
160172
var handlers = [
@@ -180,6 +192,8 @@ self.addEventListener('fetch', function(event) {
180192
{ pattern: '?keepalive', fn: handleKeepalive },
181193
{ pattern: '?isReloadNavigation', fn: handleIsReloadNavigation },
182194
{ pattern: '?isHistoryNavigation', fn: handleIsHistoryNavigation },
195+
{ pattern: '?use-and-ignore', fn: handleUseAndIgnore },
196+
{ pattern: '?clone-and-ignore', fn: handleCloneAndIgnore },
183197
];
184198

185199
var handler = null;

0 commit comments

Comments
 (0)