diff options
| author | David Lönnhager <david.l@mullvad.net> | 2021-11-03 13:12:05 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-03-14 12:08:41 +0100 |
| commit | 78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd (patch) | |
| tree | 6e453e7fb6a79cd01e6f28767c8834400f11299a | |
| parent | a5ac41cc91cd48791ce207cdae8feb8f4fe2911a (diff) | |
| download | mullvadvpn-78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd.tar.xz mullvadvpn-78f9b19f3ff4afd8f46b9bad1042a26ee808a3bd.zip | |
Handle empty REST responses generically
| -rw-r--r-- | mullvad-rpc/src/rest.rs | 41 |
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)] |
