简体   繁体   English

Rust 使用 Reqwest 处理错误响应体

[英]Rust handling error response bodies with Reqwest

I'm using the reqwest (version 0.10.4 ) crate for the HTTP calls in my Rust application but can't find any examples of how to handle APIs calls that could return more than one possible response body, mainly for error handling.我在我的 Rust 应用程序中为 HTTP 调用使用reqwest (版本0.10.4 )板条箱,但找不到任何关于如何处理可能返回多个可能响应体的 API 调用的示例,主要用于错误处理。

For instance, an API call could respond with a success JSON structure, or an error structure of format:例如,API 调用可能会以成功的 JSON 结构或以下格式的错误结构响应:

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

Currently I have this code for the function, but can't seem to figure out how to determine which struct I need to deserialize the response buffer into based on whether the HTTP request was successful or not.目前我有这个 function 的代码,但似乎无法弄清楚如何根据 HTTP 请求是否成功来确定我需要将响应缓冲区反序列化到哪个struct

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)),
    }
}

Did I miss something in the documentation for reqwest or is this a common issue?我是否遗漏了reqwest文档中的某些内容,或者这是一个常见问题?

Internally, res.json() uses the serde_json crate to deserialize the from JSON to your Rust object.在内部, res.json()使用serde_json crate 将 JSON 反序列化为 Rust object。

In Rust, when you want a type that have multiple different variants, you use an enumeration.在 Rust 中,当您想要一个具有多个不同变体的类型时,您可以使用枚举。 serde implements this behavior for you, which allows you to deserialize to an enumeration, based on the format deserialized from. serde为您实现此行为,它允许您根据反序列化的格式反序列化为枚举。 For example, you might define your response enumeration as follows:例如,您可以按如下方式定义响应枚举:

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

There is a lot going on there, but here are the highlights: #[serde(untagged)] tells serde that the enumeration should only be differentiated by the fields in Ok and Err.那里发生了很多事情,但这里是亮点: #[serde(untagged)]告诉 serde 枚举应该只通过 Ok 和 Err 中的字段来区分。 In your Rust code, you can differentiate by variant, using the full range of pattern matching, etc.在您的 Rust 代码中,您可以按变体进行区分,使用全方位的模式匹配等。

For your specific use case, it looks like the standard Result<V, E> enumeration should be good enough.对于您的特定用例,看起来标准的Result<V, E>枚举应该足够好。

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

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