Rust使用Reqwest处理错误响应体

16

我在我的Rust应用程序中使用reqwest(版本0.10.4)crate进行HTTP调用,但是找不到如何处理可能返回多个可能响应体的API调用的示例,主要是为了错误处理。

例如,API调用可以响应成功的JSON结构,或者格式为错误结构的结构:

{
    "errors": ["..."]
}

目前我有这个函数的代码,但似乎无法弄清楚如何确定需要将响应缓冲区反序列化为哪个结构体,以根据HTTP请求是否成功。

use super::responses::{Error, Response};
use crate::clients::HttpClient;
use crate::errors::HttpError;
use reqwest::header;

pub fn call() -> Result<Response, HttpError> {
    let url = format!("{}/auth/userpass/login/{}", addr, user);
    let response = HttpClient::new()
        .post(&url)
        .header(header::ACCEPT, "application/json")
        .header(header::CONTENT_TYPE, "application/json")
        .json(&serde_json::json!({ "password": pass }))
        .send();

    match response {
        Ok(res) => {
            let payload = res.json(); // could be `Error` or `Response` but only parses to `Response`
            match payload {
                Ok(j) => Ok(j),
                Err(e) => Err(HttpError::JsonParse(e)),
            }
        }
        Err(e) => Err(HttpError::RequestFailed(e)),
    }
}

我在reqwest的文档中有遗漏吗?还是这个问题比较普遍?

1个回答

12

内部,res.json()使用serde_json crate 将JSON反序列化为Rust对象。

在Rust中,当您想要一个具有多种不同变体的类型时,可以使用枚举。 serde 为您实现了此行为,使您能够根据反序列化格式反序列化到枚举中。例如,您可以按以下方式定义响应枚举:

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum ResponseType {
  Ok(/* fields */),
  Err(/* fields */),
}

这里有很多内容,但是以下是重点: #[serde(untagged)]告诉serde枚举应该只由Ok和Err中的字段区分。在您的Rust代码中,您可以通过变量进行区分,使用完整的模式匹配等。

对于您的特定用例,看起来标准的Result<V,E>枚举应该足够好用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接