summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2021-11-03 13:12:05 +0100
committerDavid Lönnhager <david.l@mullvad.net>2022-03-14 12:08:41 +0100
commit78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd (patch)
tree6e453e7fb6a79cd01e6f28767c8834400f11299a
parenta5ac41cc91cd48791ce207cdae8feb8f4fe2911a (diff)
downloadmullvadvpn-78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd.tar.xz
mullvadvpn-78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd.zip
Handle empty REST responses generically
-rw-r--r--mullvad-rpc/src/rest.rs41
1 files changed, 27 insertions, 14 deletions
diff --git a/mullvad-rpc/src/rest.rs b/mullvad-rpc/src/rest.rs
index 21599fc5a0..ca12469081 100644
--- a/mullvad-rpc/src/rest.rs
+++ b/mullvad-rpc/src/rest.rs
@@ -528,14 +528,15 @@ pub fn send_json_request<B: serde::Serialize>(
}
}
-pub async fn deserialize_body<T: serde::de::DeserializeOwned>(mut response: Response) -> Result<T> {
- let body_length: usize = response
- .headers()
- .get(header::CONTENT_LENGTH)
- .and_then(|header_value| header_value.to_str().ok())
- .and_then(|length| length.parse::<usize>().ok())
- .unwrap_or(0);
+pub async fn deserialize_body<T: serde::de::DeserializeOwned>(response: Response) -> Result<T> {
+ let body_length = get_body_length(&response);
+ deserialize_body_inner(response, body_length).await
+}
+async fn deserialize_body_inner<T: serde::de::DeserializeOwned>(
+ mut response: Response,
+ body_length: usize,
+) -> Result<T> {
let mut body: Vec<u8> = Vec::with_capacity(body_length);
while let Some(chunk) = response.body_mut().next().await {
body.extend(&chunk?);
@@ -544,6 +545,15 @@ pub async fn deserialize_body<T: serde::de::DeserializeOwned>(mut response: Resp
serde_json::from_slice(&body).map_err(Error::DeserializeError)
}
+fn get_body_length(response: &Response) -> usize {
+ response
+ .headers()
+ .get(header::CONTENT_LENGTH)
+ .and_then(|header_value| header_value.to_str().ok())
+ .and_then(|length| length.parse::<usize>().ok())
+ .unwrap_or(0)
+}
+
pub async fn parse_rest_response(
response: Response,
expected_statuses: &'static [hyper::StatusCode],
@@ -567,16 +577,19 @@ pub async fn parse_rest_response(
}
pub async fn handle_error_response<T>(response: Response) -> Result<T> {
- let error_message = match response.status() {
+ let status = response.status();
+ let error_message = match status {
hyper::StatusCode::NOT_FOUND => "Not found",
hyper::StatusCode::METHOD_NOT_ALLOWED => "Method not allowed",
- status => {
- let err: ErrorResponse = deserialize_body(response).await?;
-
- return Err(Error::ApiError(status, err.code));
- }
+ status => match get_body_length(&response) {
+ 0 => status.canonical_reason().unwrap_or("Unexpected error"),
+ body_length => {
+ let err: ErrorResponse = deserialize_body_inner(response, body_length).await?;
+ return Err(Error::ApiError(status, err.code));
+ }
+ },
};
- Err(Error::ApiError(response.status(), error_message.to_owned()))
+ Err(Error::ApiError(status, error_message.to_owned()))
}
#[derive(Clone)]