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

Code before:
        }
    }

    pub(crate) fn cancel(&mut self) {
        if let Some(request_id) = self.request_id.take() {
            // stop trying to make fetch happen
            // it's not going to happen

            if let Some(ref core_resource_thread) = self.core_resource_thread {
                // No error handling here. Cancellation is a courtesy call,
                // we don't actually care if the other side heard.
                cancel_async_fetch(vec![request_id], core_resource_thread);
            }
        }
    }

    /// Use this if you don't want it to send a cancellation request
    /// on drop (e.g. if the fetch completes)
    pub(crate) fn ignore(&mut self) {
        let _ = self.request_id.take();
    }
}

impl Drop for FetchCanceller {
    /// Step 1 of <https://fetch.spec.whatwg.org/#concept-fetch-group-terminate>
    fn drop(&mut self) {
        // Step 1. For each fetch record record of fetchGroup’s fetch records,
        // if record’s controller is non-null and record’s request’s done flag
        // is unset and keepalive is false, terminate record’s controller.
        if self.keep_alive {
            return;
        }
        self.cancel()
    }
}

fn request_init_from_request(request: NetTraitsRequest, global: &GlobalScope) -> RequestBuilder {
    let mut builder =
        RequestBuilder::new(request.target_webview_id, request.url(), request.referrer)
            .method(request.method)
            .headers(request.headers)
            .unsafe_request(request.unsafe_request)
            .body(request.body)
            .destination(request.destination)
            .synchronous(request.synchronous)
            .mode(request.mode)
            .cache_mode(request.cache_mode)
            .use_cors_preflight(request.use_cors_preflight)
            .credentials_mode(request.credentials_mode)
            .use_url_credentials(request.use_url_credentials)
            .referrer_policy(request.referrer_policy)

Review comment (suggestion):
I don't think using drop is a good idea, because it makes it unclear when the method is called, for example it will be called in case of panic as well. Also, the `cancel` method can panic itself, and that should be avoided in a drop implementation see https://doc.rust-lang.org/std/ops/trait.Drop.html#panics.

Instead you could have two methods: `terminate` and `abort`, both of which can call `cancel`, and where `terminate` is not called(or does not call `cancel`) on the canceller when the equivalent of a fetch group terminates, if the fetch is keep-alive. `cancel_all_loads` would then call `terminate` explicitly(or not call it if keep-alive).

So in this PR I would just remove the entire `self.keep_alive` conditional, and in a follow-up(s) work on implementing the keep-alive functionality as it relates to termination.

Code after:
        }
    }

    pub(crate) fn cancel(&mut self) {
        if let Some(request_id) = self.request_id.take() {
            // stop trying to make fetch happen
            // it's not going to happen

            if let Some(ref core_resource_thread) = self.core_resource_thread {
                // No error handling here. Cancellation is a courtesy call,
                // we don't actually care if the other side heard.
                cancel_async_fetch(vec![request_id], core_resource_thread);
            }
        }
    }

    /// Use this if you don't want it to send a cancellation request
    /// on drop (e.g. if the fetch completes)
    pub(crate) fn ignore(&mut self) {
        let _ = self.request_id.take();
    }
}

impl Drop for FetchCanceller {
    fn drop(&mut self) {
        self.cancel()
    }
}

fn request_init_from_request(request: NetTraitsRequest, global: &GlobalScope) -> RequestBuilder {
    let mut builder =
        RequestBuilder::new(request.target_webview_id, request.url(), request.referrer)
            .method(request.method)
            .headers(request.headers)
            .unsafe_request(request.unsafe_request)
            .body(request.body)
            .destination(request.destination)
            .synchronous(request.synchronous)
            .mode(request.mode)
            .cache_mode(request.cache_mode)
            .use_cors_preflight(request.use_cors_preflight)
            .credentials_mode(request.credentials_mode)
            .use_url_credentials(request.use_url_credentials)
            .referrer_policy(request.referrer_policy)
            .pipeline_id(request.pipeline_id)
            .redirect_mode(request.redirect_mode)
            .integrity_metadata(request.integrity_metadata)
            .cryptographic_nonce_metadata(request.cryptographic_nonce_metadata)
            .parser_metadata(request.parser_metadata)
            .initiator(request.initiator)
            .client(global.request_client())