diff --git a/src/error.rs b/src/error.rs index ce6b1ff..d79ce4b 100644 --- a/src/error.rs +++ b/src/error.rs @@ -2,6 +2,8 @@ use std::convert::From; use std::error; use std::fmt; +use reqwest::StatusCode; + /// Wraps several types of errors. #[derive(Debug)] pub struct Error { @@ -19,6 +21,13 @@ impl Error { pub fn new(kind: ErrorKind, msg: String) -> Error { Error { kind, msg } } + + pub fn http(status: StatusCode, body: String) -> Error { + Error { + kind: ErrorKind::FlagsmithAPIError, + msg: format!("HTTP Api error: {status}, {body}"), + } + } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -48,3 +57,26 @@ impl From for Error { Error::new(ErrorKind::FlagsmithAPIError, e.to_string()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_http_error_includes_status_and_body() { + let error = Error::http( + StatusCode::BAD_GATEWAY, + "{\"detail\":\"upstream unavailable\"}".to_string(), + ); + + assert_eq!(error.kind, ErrorKind::FlagsmithAPIError); + assert_eq!( + error.msg, + "HTTP Api error: 502 Bad Gateway, {\"detail\":\"upstream unavailable\"}" + ); + assert_eq!( + error.to_string(), + "Flagsmith API error: HTTP Api error: 502 Bad Gateway, {\"detail\":\"upstream unavailable\"}" + ); + } +} diff --git a/src/flagsmith/mod.rs b/src/flagsmith/mod.rs index 3051748..5a22901 100644 --- a/src/flagsmith/mod.rs +++ b/src/flagsmith/mod.rs @@ -434,13 +434,11 @@ fn get_json_response( request = request.body(body.unwrap()); }; let response = request.send()?; - if response.status().is_success() { + let status = response.status(); + if status.is_success() { return Ok(response.json()?); } else { - return Err(error::Error::new( - error::ErrorKind::FlagsmithAPIError, - response.text()?, - )); + return Err(error::Error::http(status, response.text()?)); } } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index f186871..92c54a6 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -712,7 +712,8 @@ fn test_flagsmith_api_error_is_returned_if_something_goes_wrong_with_the_request when.method(GET) .path("/api/v1/flags/") .header("X-Environment-Key", ENVIRONMENT_KEY); - then.status(502).json_body({}); // returning 502 + then.status(502) + .json_body(serde_json::json!({"detail": "bad gateway"})); // returning 502 }); let url = mock_server.url("/api/v1/"); let flagsmith_options = FlagsmithOptions { @@ -723,7 +724,19 @@ fn test_flagsmith_api_error_is_returned_if_something_goes_wrong_with_the_request // When let err = flagsmith.get_environment_flags().err().unwrap(); + + // Then: the error carries the HTTP status and the response body assert_eq!(err.kind, flagsmith::error::ErrorKind::FlagsmithAPIError); + assert!( + err.msg.contains("502 Bad Gateway"), + "unexpected msg: {}", + err.msg + ); + assert!( + err.msg.contains("bad gateway"), + "unexpected msg: {}", + err.msg + ); } #[rstest]