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.
For instance, an API call could respond with a success JSON structure, or an error structure of format:
{
"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.
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?
Internally, res.json()
uses the serde_json
crate to deserialize the from JSON to your Rust object.
In Rust, when you want a type that have multiple different variants, you use an enumeration. serde
implements this behavior for you, which allows you to deserialize to an enumeration, based on the format deserialized from. 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. In your Rust code, you can differentiate by variant, using the full range of pattern matching, etc.
For your specific use case, it looks like the standard Result<V, E>
enumeration should be good enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With