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.
In addition to the hint posted in the comments (using filter_map
), you can save performace by not copying all collections/strings involved:
String
, you can do the lookup using &str
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);
}
}