http_request_derive/
from_http_response.rs1use bytes::Bytes;
6
7use crate::Error;
8
9pub trait FromHttpResponse {
11 fn from_http_response(http_response: http::Response<Bytes>) -> Result<Self, Error>
22 where
23 Self: Sized;
24}
25
26#[cfg(feature = "serde")]
27impl<D> FromHttpResponse for D
28where
29 D: serde::de::DeserializeOwned,
30{
31 fn from_http_response(http_response: http::Response<Bytes>) -> Result<Self, Error> {
32 use snafu::ResultExt as _;
33
34 let status = http_response.status();
35
36 snafu::ensure!(
37 status.is_success(),
38 crate::error::NonSuccessStatusSnafu {
39 status,
40 body: http_response.into_body()
41 }
42 );
43 serde_json::from_slice(http_response.body()).context(crate::error::JsonSnafu)
44 }
45}
46
47#[cfg(all(test, feature = "serde"))]
48mod serde_tests {
49 use http::StatusCode;
50 use serde::Deserialize;
51
52 use super::*;
53
54 #[derive(Deserialize, Debug, PartialEq)]
55 struct TestStruct {
56 id: i32,
57 name: String,
58 }
59
60 #[tokio::test]
61 async fn test_from_response_success() {
62 let response = http::Response::builder()
63 .status(StatusCode::OK)
64 .header("content-type", "application/json")
65 .body(Bytes::from_static(r#"{"id":1,"name":"Test"}"#.as_bytes()))
66 .expect("valid response required");
67
68 let result = TestStruct::from_http_response(response);
69 assert!(result.is_ok());
70 assert_eq!(
71 result.unwrap(),
72 TestStruct {
73 id: 1,
74 name: "Test".to_string()
75 }
76 );
77 }
78
79 #[tokio::test]
80 async fn test_from_response_invalid_json() {
81 let response = http::Response::builder()
82 .status(StatusCode::OK)
83 .header("content-type", "application/json")
84 .body(Bytes::from_static(r#"{"id":1,"name":"Test"#.as_bytes()))
85 .expect("valid response required");
86
87 let result = TestStruct::from_http_response(response);
88 assert!(result.is_err());
89 assert!(matches!(result.unwrap_err(), Error::Json { .. }));
90 }
91}