Repository: servo/servo
File: components/shared/net/request.rs (Rust)

Code before:
    ordered_set.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap());
    ordered_set.dedup();
    ordered_set.into_iter().cloned().collect()
}

pub fn create_request_body_with_content(content: &str) -> RequestBody {
    let content_bytes = GenericSharedMemory::from_bytes(content.as_bytes());
    let content_len = content_bytes.len();

    let (chunk_request_sender, chunk_request_receiver) = ipc::channel().unwrap();
    ROUTER.add_typed_route(
        chunk_request_receiver,
        Box::new(move |message| {
            let request = message.unwrap();
            if let BodyChunkRequest::Connect(sender) = request {
                let _ = sender.send(BodyChunkResponse::Chunk(content_bytes.clone()));
                let _ = sender.send(BodyChunkResponse::Done);
            }
        }),
    );

    RequestBody::new(chunk_request_sender, BodySource::Object, Some(content_len))
}

/// <https://fetch.spec.whatwg.org/#concept-request-tainted-origin>
pub fn redirect_taint_for_request(request: &Request) -> RedirectTaint {
    // Step 1. Assert: request’s origin is not "client".
    let Origin::Origin(request_origin) = &request.origin else {
        panic!("origin cannot be \"client\" at this point in time");
    };

    // Step 2. Let lastURL be null.
    let mut last_url = None;

    // Step3. Let taint be "same-origin".
    let mut taint = RedirectTaint::SameOrigin;

    // Step 4. For each url of request’s URL list:
    for url in &request.url_list {
        // Step 4.1 If lastURL is null, then set lastURL to url and continue.
        let Some(last_url) = &mut last_url else {
            last_url = Some(url);
            continue;
        };

        // Step 4.2. If url’s origin is not same site with lastURL’s origin and
        // request’s origin is not same site with lastURL’s origin, then return "cross-site".
        if !is_same_site(&url.origin(), &last_url.origin()) &&
            !is_same_site(request_origin, &last_url.origin())
        {
            return RedirectTaint::CrossSite;

Review comment (suggestion):
Any reason not to put this into the `impl Request` block? Seems like an obvious struct method. Please go ahead and do this unless there is a good reason I'm not seeing here.

Code after:
    matches!(*method, Method::GET | Method::HEAD | Method::POST)
}

/// <https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name>
pub fn is_cors_non_wildcard_request_header_name(name: &HeaderName) -> bool {
    name == AUTHORIZATION
}

/// <https://fetch.spec.whatwg.org/#cors-unsafe-request-header-names>
pub fn get_cors_unsafe_header_names(headers: &HeaderMap) -> Vec<HeaderName> {
    // Step 1
    let mut unsafe_names: Vec<&HeaderName> = vec![];
    // Step 2
    let mut potentillay_unsafe_names: Vec<&HeaderName> = vec![];
    // Step 3
    let mut safelist_value_size = 0;

    // Step 4
    for (name, value) in headers.iter() {
        if !is_cors_safelisted_request_header(&name, &value) {
            unsafe_names.push(name);
        } else {
            potentillay_unsafe_names.push(name);
            safelist_value_size += value.as_ref().len();
        }
    }

    // Step 5
    if safelist_value_size > 1024 {
        unsafe_names.extend_from_slice(&potentillay_unsafe_names);
    }

    // Step 6
    convert_header_names_to_sorted_lowercase_set(unsafe_names)
}

/// <https://fetch.spec.whatwg.org/#ref-for-convert-header-names-to-a-sorted-lowercase-set>
pub fn convert_header_names_to_sorted_lowercase_set(
    header_names: Vec<&HeaderName>,
) -> Vec<HeaderName> {
    // HeaderName does not implement the needed traits to use a BTreeSet
    // So create a new Vec, sort, then dedup
    let mut ordered_set = header_names.to_vec();
    ordered_set.sort_by(|a, b| a.as_str().partial_cmp(b.as_str()).unwrap());
    ordered_set.dedup();
    ordered_set.into_iter().cloned().collect()
}

pub fn create_request_body_with_content(content: &str) -> RequestBody {
    let content_bytes = GenericSharedMemory::from_bytes(content.as_bytes());
    let content_len = content_bytes.len();