I have a situation where I want to read some headers via reqwest::header::HeaderValue
I am doing so using
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let url = "https://httpbin.org/get";
let resp = reqwest::Client::new().get(url).send().await?;
// read response headers
// default if the header does not exist
let resp_headers: &str = resp
.headers()
.get("content-length")
.unwrap_or(&reqwest::header::HeaderValue::from_str("100").unwrap())
.to_str()
.unwrap_or("100");
println!("{}", resp_headers);
Ok(())
}
This doesn't seem idiomatic and won't compile. Looking for how to approach a scenario like this where there are several necessary unwraps to process and cast a type into desired end result.
You could use a named block and let-else statements.
let resp_headers: &str = 'block: {
let Some(content_length) = resp.headers().get(reqwest::header::CONTENT_LENGTH) else {
break 'block "100";
};
let Ok(content_length) = content_length.to_str() else {
break 'block "100";
};
content_length
};
Or if you intend to keep the two unwrap values the same, you could use Option::and_then
.
let resp_headers: &str = resp
.headers()
.get(reqwest::header::CONTENT_LENGTH)
.and_then(|content_length| content_length.to_str().ok())
.unwrap_or("100");
Or you can put this in a function and use ?
.
fn read_content_length(resp: &reqwest::Response) -> Option<&str> {
resp.headers()
.get(reqwest::header::CONTENT_LENGTH)?
.to_str()
.ok()
}
let resp_headers: &str = read_content_length(&resp).unwrap_or("100");
But specifically for the content-length
header, there is Response::content_length
.
let resp_headers: u64 = resp.content_length().unwrap_or(100);