简体   繁体   English

Rust:使用reqwest处理响应错误

[英]Rust: Response error handling using reqwest

Ok, so I'm very new to Rust and I'm trying to clumsily piece together a little CLI tool that makes http requests and handles the responses, by using tokio, clap, reqwest and serde.好的,所以我对 Rust 很陌生,我正在尝试笨拙地拼凑一个小的 CLI 工具,它通过使用 tokio、clap、reqwest 和 serde 发出 http 请求并处理响应。

The tool accepts a customer number as input and then it tries to fetch information about the customer.该工具接受客户编号作为输入,然后尝试获取有关客户的信息。 The customer may or may not have a FooBar in each country.客户在每个国家可能有也可能没有 FooBar。

My code currently only works if I get a nice 200 response containing a FooBar.我的代码目前只有在收到包含 FooBar 的漂亮 200 响应时才有效。 If I don't, the deserialization fails (naturally).如果我不这样做,反序列化就会失败(自然)。 (Edit: Actually, this initial assumption about the problem seems to be false, see comments below) (编辑:实际上,这个关于问题的初步假设似乎是错误的,见下面的评论)

My aim is to only attempt the deserialization if I actually get a valid response.我的目标是仅在我确实得到有效响应时才尝试反序列化。

How would I do that?我该怎么做? I feel the need to see the code of a valid approach to understand this better.我觉得有必要查看有效方法的代码以更好地理解这一点。

Below is the entirety of my program.下面是我的整个程序。


use clap::Parser;
use reqwest::Response;
use serde::{Deserialize, Serialize};

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let args: Cli = Cli::parse();

    let client = reqwest::Client::new();

    let countries = vec!["FR", "GB", "DE", "US"];

    for country in countries.iter() {
        let foo_bar : FooBar = client.get(
            format!("http://example-service.com/countries/{}/customers/{}/foo_bar", country, args.customer_number))
            .send()
            .await?
            .json()
            .await?;

        println!("{}", foo_bar.a_value);
    }

    Ok(())
}

#[derive(Debug, Serialize, Deserialize)]
struct FooBar {
    a_value: String,
}

#[derive(Parser, Debug)]
struct Cli {
    customer_number: i32,
}

There are a few ways to approach this issue, first of all you can split the json() deserialization from send().await , ie:有几种方法可以解决此问题,首先您可以将json()反序列化与send().await分开,即:

    for country in countries.iter() {
        let resp: reqwest::Response = client.get(
            format!("http://example-service.com/countries/{}/customers/{}/foo_bar", country, args.customer_number))
            .send()
            .await?;
        if resp.status() != reqwest::StatusCode::OK {
             eprintln!("didn't get OK status: {}", resp.status());
        } else {
             let foo_bar = resp.json().await?;
             println!("{}", foo_bar.a_value);
        }
    }

If you want to keep the response body around, you can extract it through let bytes = resp.bytes().await?;如果你想保留响应主体,你可以通过let bytes = resp.bytes().await?;提取它。 and pass bytes to serde_json::from_slice(&*bytes) for the deserialization attempt.并将bytes传递给serde_json::from_slice(&*bytes)以进行反序列化尝试。

This can be useful if you have a set of expected error response bodies.如果您有一组预期的错误响应主体,这将很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM