Rust 使用 Reqwest 处理错误响应主体
Rust handling error response bodies with Reqwest
我在我的 Rust 应用程序中使用 reqwest
(版本 0.10.4
)包进行 HTTP 调用,但找不到任何有关如何处理 API 调用的示例这可能 return 不止一种可能的响应主体,主要用于错误处理。
例如,API 调用可以响应成功 JSON 结构,或格式错误结构:
{
"errors": ["..."]
}
目前我有这个函数的代码,但似乎无法弄清楚如何根据 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)),
}
}
我是否遗漏了 reqwest
文档中的某些内容,或者这是一个常见问题?
在内部,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>
枚举应该足够好。
我在我的 Rust 应用程序中使用 reqwest
(版本 0.10.4
)包进行 HTTP 调用,但找不到任何有关如何处理 API 调用的示例这可能 return 不止一种可能的响应主体,主要用于错误处理。
例如,API 调用可以响应成功 JSON 结构,或格式错误结构:
{
"errors": ["..."]
}
目前我有这个函数的代码,但似乎无法弄清楚如何根据 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)),
}
}
我是否遗漏了 reqwest
文档中的某些内容,或者这是一个常见问题?
在内部,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>
枚举应该足够好。