Reqwest: 读取请求体文本并返回 reqwest::Error

huangapple go评论65阅读模式
英文:

Reqwest: read body text and return reqwest::Error

问题

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    println!("received text: {:?}", response.text().await?);
    response.error_for_status()?;
    Ok(())
}
英文:

I want to use reqwest to make a request, then print the response's body and return a reqwest::Error if the status code was >= 400. This is how I would like to do this:

pub async fn print_body() -&gt; Result&lt;(), reqwest::Error&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org&quot;).await?;
    println!(&quot;received text: {:?}&quot;, response.text().await?);
    response.error_for_status()?;
    Ok(())

The trouble is that both response.text() and response.error_for_status() consume the response. Debug printing the response itself or the error from response.error_for_status() does not print the response body.

I've tried saving the status code, then generating a reqwest::Error if the status code is >= 400, but reqwest::Error is not meant to be constructed by library users since its inner field and constructor are private. Ideally a reqwest::Error is returned since other functions depend on this API, and I would like to understand if it's possible to achieve this without changing the public interface.

Rust playground link

答案1

得分: 2

你可能忽略了error_for_status_ref()方法,它不会消耗响应。只需要交换调用的顺序:

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    response.error_for_status_ref()?;
    println!("received text: {:?}", response.text().await?);
    Ok(())
}

要始终打印文本,只需存储error_for_status_ref()的结果,并将引用映射到Ok情况,使其为(),以匹配函数的返回类型:

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    let result = response.error_for_status_ref().map(|_| ());
    println!("received text: {:?}", response.text().await?);
    result
}
英文:

You might have glossed over the error_for_status_ref() method, which does not consume the response. You just need to swap the order of the calls:

pub async fn print_body() -&gt; Result&lt;(), reqwest::Error&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org&quot;).await?;
    response.error_for_status_ref()?;
    println!(&quot;received text: {:?}&quot;, response.text().await?);
    Ok(())
}

To print the text regardless, just store the result of error_for_status_ref() and map the reference in the Ok case to be () to match the return type of your function:

pub async fn print_body() -&gt; Result&lt;(), reqwest::Error&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org&quot;).await?;
    let result = response.error_for_status_ref().map(|_| ());
    println!(&quot;received text: {:?}&quot;, response.text().await?);
    result
}

答案2

得分: 2

没有问题,如果你在检索文本之前处理了错误情况,因为error_for_status在一切正常时返回Response

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    println!("received text: {:?}", response.error_for_status()?.text().await?);
    Ok(())
}
英文:

There is no issue if you handle your error case before you retreive the text as error_for_status returns the Response if everything is ok:

pub async fn print_body() -&gt; Result&lt;(), reqwest::Error&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org&quot;).await?;
    println!(&quot;received text: {:?}&quot;, response.error_for_status()?.text().await?);
    Ok(())
}

答案3

得分: 0

谢谢 @cafce25 指出 error_for_status_ref,我最初忽略了它,因为它在 Ok() 时返回对 self 的引用,如果我试图在调用 .text() 后保留完整的结果以供使用,将会给我编译器错误。但使用 .err() 仅提取错误部分可以解决此问题:

pub async fn print_body() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://www.rust-lang.org").await?;
    let maybe_err = response.error_for_status_ref().err();
    println!("received text: {:?}", response.text().await?);
    match maybe_err {
        Some(e) => Err(e),
        None => Ok(()),
    }
}
英文:

Thank you, @cafce25 for pointing me back to error_for_status_ref, which I originally passed over since it returns a reference to self on Ok(), giving me compiler errors if I tried to keep the full result to use after calling .text(). But grabbing just the error with .err() resolves it:

pub async fn print_body() -&gt; Result&lt;(), reqwest::Error&gt; {
    let response = reqwest::get(&quot;https://www.rust-lang.org&quot;).await?;
    let maybe_err = response.error_for_status_ref().err();
    println!(&quot;received text: {:?}&quot;, response.text().await?);
    match maybe_err {
        Some(e) =&gt; Err(e),
        None =&gt; Ok(()),
    }
}

huangapple
  • 本文由 发表于 2023年2月24日 06:53:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定