http_request_derive/
from_http_response.rs1use async_trait::async_trait;
6use bytes::Bytes;
7
8use crate::Error;
9
10#[async_trait]
12pub trait FromHttpResponse {
13 fn from_http_response(http_response: http::Response<Bytes>) -> Result<Self, Error>
24 where
25 Self: Sized;
26
27 #[cfg(feature = "reqwest")]
38 async fn from_reqwest_response(response: reqwest::Response) -> Result<Self, Error>
39 where
40 Self: Sized;
41}
42
43#[cfg(feature = "serde")]
44#[async_trait]
45impl<D> FromHttpResponse for D
46where
47 D: serde::de::DeserializeOwned,
48{
49 fn from_http_response(http_response: http::Response<Bytes>) -> Result<Self, Error> {
50 use snafu::ResultExt as _;
51 serde_json::from_slice(http_response.body()).context(crate::error::JsonSnafu)
52 }
53
54 #[cfg(feature = "reqwest")]
55 async fn from_reqwest_response(response: reqwest::Response) -> Result<Self, Error>
56 where
57 Self: Sized,
58 {
59 use snafu::ResultExt as _;
60
61 use crate::error::ReqwestSnafu;
62
63 serde_json::from_slice(&response.bytes().await.context(ReqwestSnafu {
64 message: "Failed to receive success response",
65 })?)
66 .context(crate::error::JsonSnafu)
67 }
68}
69
70#[cfg(all(test, feature = "reqwest", feature = "serde"))]
71mod serde_reqwest_tests {
72 use reqwest::Client;
73 use serde::Deserialize;
74
75 use super::*;
76
77 #[derive(Deserialize, Debug, PartialEq)]
78 struct TestStruct {
79 id: i32,
80 name: String,
81 }
82
83 #[tokio::test]
84 async fn test_from_reqwest_response_success() {
85 let mut server = mockito::Server::new_async().await;
86 let _m = server
87 .mock("GET", "/test")
88 .with_status(200)
89 .with_header("content-type", "application/json")
90 .with_body(r#"{"id": 1, "name": "Test"}"#)
91 .create_async()
92 .await;
93
94 let client = Client::new();
95 let response = client
96 .get(format!("{}/test", server.url()))
97 .send()
98 .await
99 .unwrap();
100
101 let result = TestStruct::from_reqwest_response(response).await;
102 assert!(result.is_ok());
103 assert_eq!(
104 result.unwrap(),
105 TestStruct {
106 id: 1,
107 name: "Test".to_string()
108 }
109 );
110 }
111
112 #[tokio::test]
113 async fn test_from_reqwest_response_invalid_json() {
114 let mut server = mockito::Server::new_async().await;
115 let _m = server
116 .mock("GET", "/test")
117 .with_status(200)
118 .with_header("content-type", "application/json")
119 .with_body(r#"{"id": 1, "name": "Test"#)
120 .create_async()
121 .await;
122
123 let client = Client::new();
124 let response = client
125 .get(format!("{}/test", server.url()))
126 .send()
127 .await
128 .unwrap();
129
130 let result = TestStruct::from_reqwest_response(response).await;
131 assert!(result.is_err());
132 assert!(matches!(result.unwrap_err(), Error::Json { .. }));
133 }
134}