Repository: servo/servo
File: components/script/dom/navigator.rs (Rust)

Code before:
                // set corsMode to "no-cors".
                if is_cors_safelisted_request_content_type(content_type.as_bytes()) {
                    cors_mode = RequestMode::NoCors;
                }
                // Append a Content-Type header with value contentType to headerList.
                //
                // We cannot use typed header insertion with `mime::Mime` parsing here,
                // since it lowercases `charset=UTF-8`: https://github.com/hyperium/mime/issues/116
                headers.insert(
                    header::CONTENT_TYPE,
                    HeaderValue::from_str(content_type).unwrap(),
                );
            }
            request_body = Some(extracted_body.into_net_request_body().0);
        }
        // Step 7.1. Let req be a new request, initialized as follows:
        let request = RequestBuilder::new(None, url.clone(), global.get_referrer())
            .mode(cors_mode)
            .destination(Destination::None)
            .policy_container(global.policy_container())
            .insecure_requests_policy(global.insecure_requests_policy())
            .has_trustworthy_ancestor_origin(global.has_trustworthy_ancestor_or_current_origin())
            .method(http::Method::POST)
            .body(request_body)
            .origin(origin)
            // TODO: Set keep-alive flag
            .credentials_mode(CredentialsMode::Include)
            .headers(headers);
        // Step 7.2. Fetch req.
        global.fetch(
            request,
            Arc::new(Mutex::new(BeaconFetchListener {
                url,
                global: Trusted::new(&global),
                resource_timing: ResourceFetchTiming::new(ResourceTimingType::None),
            })),
            global.task_manager().networking_task_source().into(),
        );
        // Step 7. Set the return value to true, return the sendBeacon() call, and continue to run the following steps in parallel:
        Ok(true)
    }

    /// <https://servo.org/internal-no-spec>
    fn Servo(&self) -> DomRoot<ServoInternals> {
        self.servo_internals
            .or_init(|| ServoInternals::new(&self.global(), CanGc::note()))
    }
}

struct BeaconFetchListener {
    /// URL of this request.

Review comment (suggestion):
I've looked at `navigator.sendBeacon` before and if I recall correctly then the keep-alive is a fairly crucial part of the API 😅 . `sendBeacon` is usually called when the user navigates away from a page, to send analytics to the server for example and I believe the keep-alive flag tells fetch to complete the request even if the originating browsing context no longer exists.

TLDR; I'm not sure how useful this API is without the flag ):

Code after:
                // set corsMode to "no-cors".
                if is_cors_safelisted_request_content_type(content_type.as_bytes()) {
                    cors_mode = RequestMode::NoCors;
                }
                // Append a Content-Type header with value contentType to headerList.
                //
                // We cannot use typed header insertion with `mime::Mime` parsing here,
                // since it lowercases `charset=UTF-8`: https://github.com/hyperium/mime/issues/116
                headers.insert(
                    header::CONTENT_TYPE,
                    HeaderValue::from_str(content_type).unwrap(),
                );
            }
            request_body = Some(extracted_body.into_net_request_body().0);
        }
        // Step 7.1. Let req be a new request, initialized as follows:
        let request = RequestBuilder::new(None, url.clone(), global.get_referrer())
            .mode(cors_mode)
            .destination(Destination::None)
            .policy_container(global.policy_container())
            .insecure_requests_policy(global.insecure_requests_policy())
            .has_trustworthy_ancestor_origin(global.has_trustworthy_ancestor_or_current_origin())
            .method(http::Method::POST)
            .body(request_body)
            .origin(origin)
            // TODO: Set keep-alive flag
            .credentials_mode(CredentialsMode::Include)
            .headers(headers);
        // Step 7.2. Fetch req.
        global.fetch(
            request,
            Arc::new(Mutex::new(BeaconFetchListener {
                url,
                global: Trusted::new(&global),
                resource_timing: ResourceFetchTiming::new(ResourceTimingType::None),
            })),
            global.task_manager().networking_task_source().into(),
        );
        // Step 7. Set the return value to true, return the sendBeacon() call,
        // and continue to run the following steps in parallel:
        Ok(true)
    }

    /// <https://servo.org/internal-no-spec>
    fn Servo(&self) -> DomRoot<ServoInternals> {
        self.servo_internals
            .or_init(|| ServoInternals::new(&self.global(), CanGc::note()))
    }
}

struct BeaconFetchListener {