Closed Bug 1567738 Opened 6 years ago Closed 6 years ago

Fetch API not working in beforeunload

Categories

(Core :: DOM: Networking, defect)

68 Branch
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: colin.dumitru, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0

Steps to reproduce:

Attempted to perform a network request using fetch API during the beforeunload event, but a "TypeError: NetworkError when attempting to fetch resource" error is thrown. Request is Attempted on the same domain.

Steps to reproduce:

  • Go to https://www.amazon.com/
  • Type the following in the console:
    window.addEventListener("beforeunload", () => { fetch('/ping', {method: 'POST'}) })
  • Reload page. The "TypeError: NetworkError when attempting to fetch resource." error is thrown and the request is not made.
  • Perform the same request without the beforeunload handler:
    fetch('/ping', {method: 'POST'})
  • The request is performed normally now.

Seeing as it's a request to the same domain, CORS shouldn't be an issue, and the error is not descriptive enough to figure out what is wrong.

Content blocking was turned off. Experiment was made in private mode with no extensions active.

Actual results:

Request is not made only during the beforeunload event (including when the "keepalive" flag is set - so it kinda defeats the purpose of the fetch API). The following error is thrown:

"TypeError: NetworkError when attempting to fetch resource"

Expected results:

The request should have gone through.

Has STR: --- → yes
Component: Untriaged → DOM: Networking
Product: Firefox → Core

The request is started, but is canceled almost immediately due to navigation away from the page. The standard says that the purpose of beforeunload event is to show a warning prompt. If the prompt is shown and there is enough time to finish the request, it's done successfully. I.e. following works:

window.addEventListener('beforeunload', (event) => {
fetch('/ping', {method: 'POST'});
event.preventDefault();
event.returnValue = '';
});

Otherwise the request is canceled due to reload:
#0 0x00007f4692423c54 in mozilla::net::HttpChannelChild::Cancel(nsresult) (this=0x7f4678ec4800, status=-2142568446)
at /mnt/work/opt/moz/hg-central/netwerk/protocol/http/HttpChannelChild.cpp:2415
#1 0x00007f4691e1d75b in mozilla::net::nsLoadGroup::Cancel(nsresult) (this=0x7f467b86afc0, status=-2142568446)
at /mnt/work/opt/moz/hg-central/netwerk/base/nsLoadGroup.cpp:224
#2 0x00007f469349e828 in nsDocLoader::Stop() (this=0x7f467c4e0800) at /mnt/work/opt/moz/hg-central/uriloader/base/nsDocLoader.cpp:235
#3 0x00007f469959ddd5 in nsDocShell::Stop() (this=0x7f467c4e0800) at /mnt/work/opt/moz/hg-central/docshell/base/nsDocShell.h:209
#4 0x00007f469953e5b2 in nsDocShell::Stop(unsigned int) (this=0x7f467c4e0800, aStopFlags=1) at /mnt/work/opt/moz/hg-central/docshell/base/nsDocShell.cpp:4769
#5 0x00007f469954d70c in nsDocShell::InternalLoad(nsDocShellLoadState*, nsIDocShell**, nsIRequest**)
(this=0x7f467c4e0800, aLoadState=0x7f467b8424a0, aDocShell=0x0, aRequest=0x0) at /mnt/work/opt/moz/hg-central/docshell/base/nsDocShell.cpp:9664
#6 0x00007f469954b787 in nsDocShell::LoadHistoryEntry(nsISHEntry*, unsigned int) (this=0x7f467c4e0800, aEntry=0x7f467bcab2e0, aLoadType=2)
at /mnt/work/opt/moz/hg-central/docshell/base/nsDocShell.cpp:11905
#7 0x00007f46995628fe in nsDocShell::Reload(unsigned int) (this=0x7f467c4e0800, aReloadFlags=0) at /mnt/work/opt/moz/hg-central/docshell/base/nsDocShell.cpp:4655
#8 0x00007f4691c3ca66 in NS_InvokeByIndex () at /mnt/work/opt/moz/hg-central/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S:106
#9 0x00007f469313f1f4 in CallMethodHelper::Invoke() (this=0x7ffcbcd39758) at /mnt/work/opt/moz/hg-central/js/xpconnect/src/XPCWrappedNative.cpp:1658
#10 0x00007f469313711f in CallMethodHelper::Call() (this=0x7ffcbcd39758) at /mnt/work/opt/moz/hg-central/js/xpconnect/src/XPCWrappedNative.cpp:1195

Status: UNCONFIRMED → RESOLVED
Closed: 6 years ago
Resolution: --- → WORKSFORME

I understand the concern around navigating away from the page, but shouldn't the keepalive flag guarantee that the request is made even if the current page is closed?

The following still doesn't work on Firefox, while it does on other browsers.

window.addEventListener("beforeunload", () => { fetch('/ping', {method: 'POST', keepalive: true}) })
You need to log in before you can comment on or make changes to this bug.