in glean/src/platform/browser/fetch_uploader.ts [16:69]
async post(
url: string,
pingRequest: PingRequest<string | Uint8Array>,
keepalive = true
): Promise<UploadResult> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
// We expect to have a gzipped payload.
const gzipRequest = pingRequest.asCompressedPayload();
let response;
try {
response = await fetch(url.toString(), {
headers: gzipRequest.headers,
method: "POST",
body: gzipRequest.payload,
keepalive,
// Strips any cookies or authorization headers from the request.
credentials: "omit",
signal: controller.signal,
redirect: "error",
});
} catch(e) {
// If we time out and call controller.abort,
// the fetch API will throw a DOMException with name "AbortError".
if (e instanceof DOMException) {
log(LOG_TAG, ["Timeout while attempting to upload ping.\n", e], LoggingLevel.Error);
} else if (e instanceof TypeError) {
if (keepalive) {
// Try again without `keepalive`, because that may be the issue.
// This problem was observed in chromium versions below v81.
// See: https://chromium.googlesource.com/chromium/src/+/26d70b36dd1c18244fb17b91d275332c8b73eab3
return this.post(url, gzipRequest, false);
}
// From MDN: "A fetch() promise will reject with a TypeError
// when a network error is encountered or CORS is misconfigured on the server-side,
// although this usually means permission issues or similar"
// See: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#checking_that_the_fetch_was_successful
//
// We will treat this as we treat server / network errors in this case.
log(LOG_TAG, ["Network error while attempting to upload ping.\n", e], LoggingLevel.Error);
} else {
log(LOG_TAG, ["Unknown error while attempting to upload ping.\n", e], LoggingLevel.Error);
}
clearTimeout(timeout);
return new UploadResult(UploadResultStatus.RecoverableFailure);
}
clearTimeout(timeout);
return new UploadResult(UploadResultStatus.Success, response.status);
}