rustreqwest

&Option<HeaderName> to &HeaderName


I'm making proxy using axum for accepting request from browser and reqwest for sending request to target host in Rust. So I have to change axum request to reqwest request and remove some headers like host, origin, etc. This is my remove function.

pub fn remove_headers(request: &reqwest::Request, keys_to_remove: Vec<String>) -> HeaderMap {
    let mut cloned_headers = request.headers().clone();

    // Convert keys_to_remove into a set for fast lookups
    let keys_set: HashSet<String> = keys_to_remove.into_iter().collect();

    // Create a new HeaderMap and only insert headers that are not in the keys_to_remove list
    let filtered_headers = cloned_headers
        .into_iter()
        .filter(|(key, _)| {
            // Dereference the key from &Option<HeaderName> to HeaderName and compare with the set
            if let Some(header_name) = key {
                !keys_set.contains(&header_name.as_str().to_string())
            } else {
                key.is_some()
            }
        })
        .collect::<HeaderMap>(); // Collect back into a HeaderMap

    filtered_headers
}

I expect the type of key is &HeaderName, but now &Option. So filtered_headers is not converted to HeaderMap.


Solution

  • In addition to the hint posted in the comments (using filter_map), you can save performace by not copying all collections/strings involved:

    fn remove_headers(request: &Request, keys_to_remove: &HashSet<String>) -> HeaderMap {
        request
            .headers()
            .iter()
            .filter_map(|(key, value)| {
                if !keys_to_remove.contains(key.as_str()) {
                    Some((key.clone(), value.clone()))
                } else {
                    None
                }
            })
            .collect()
    }
    

    Note that if you can mutate request, you can simply use HeaderMap::remove:

    fn remove_headers(request: &mut Request, keys_to_remove: &Vec<String>) {
        for key in keys_to_remove {
            request.headers_mut().remove(key);
        }
    }