qiniu_http_client/client/response/
mod.rs1use assert_impl::assert_impl;
2use qiniu_credential::HeaderValue;
3use qiniu_http::{
4 Response as HttpResponse, ResponseErrorKind as HttpResponseErrorKind, ResponseParts as HttpResponseParts,
5};
6use serde::{de::DeserializeOwned, Deserialize};
7use std::{
8 io::copy as io_copy,
9 mem::take,
10 ops::{Deref, DerefMut},
11};
12use tap::TapFallible;
13
14mod error;
15pub(super) use error::XHeaders;
16pub use error::{Error as ResponseError, ErrorKind as ResponseErrorKind};
17
18pub type ApiResult<T> = Result<T, ResponseError>;
20
21use qiniu_http::SyncResponseBody;
22
23#[cfg(feature = "async")]
24use futures::io::copy as async_io_copy;
25
26#[cfg(feature = "async")]
27use qiniu_http::AsyncResponseBody;
28
29const X_REQ_ID_HEADER_NAME: &str = "x-reqid";
30const X_LOG_HEADER_NAME: &str = "x-log";
31
32#[derive(Default, Debug)]
34pub struct Response<B>(HttpResponse<B>);
35
36impl<B> Response<B> {
37 #[inline]
39 pub fn into_body(self) -> B {
40 self.0.into_body()
41 }
42
43 #[inline]
45 pub fn into_parts_and_body(self) -> (HttpResponseParts, B) {
46 self.0.into_parts_and_body()
47 }
48
49 #[inline]
51 pub fn from_parts_and_body(parts: HttpResponseParts, body: B) -> Self {
52 Self(HttpResponse::from_parts_and_body(parts, body))
53 }
54
55 #[inline]
57 pub fn x_reqid(&self) -> Option<&HeaderValue> {
58 self.header(X_REQ_ID_HEADER_NAME)
59 }
60
61 #[inline]
63 pub fn x_log(&self) -> Option<&HeaderValue> {
64 self.header(X_LOG_HEADER_NAME)
65 }
66}
67
68impl<B> From<HttpResponse<B>> for Response<B> {
69 #[inline]
70 fn from(response: HttpResponse<B>) -> Self {
71 Self(response)
72 }
73}
74
75impl<B> From<Response<B>> for HttpResponse<B> {
76 #[inline]
77 fn from(response: Response<B>) -> Self {
78 response.0
79 }
80}
81
82impl<B> Deref for Response<B> {
83 type Target = HttpResponse<B>;
84
85 #[inline]
86 fn deref(&self) -> &Self::Target {
87 &self.0
88 }
89}
90
91impl<B> DerefMut for Response<B> {
92 #[inline]
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 &mut self.0
95 }
96}
97
98impl<B: Sync + Send> Response<B> {
99 #[allow(dead_code)]
100 fn assert() {
101 assert_impl!(Send: Self);
102 assert_impl!(Sync: Self);
103 }
104}
105
106impl Response<SyncResponseBody> {
107 pub fn parse_json<T: DeserializeOwned>(self) -> ApiResult<Response<T>> {
109 let x_headers = XHeaders::from(self.parts());
110 let mut got_body = Vec::new();
111 let json_response = self
112 .fulfill()?
113 .try_map_body(|mut body| parse_json_from_slice(&body).tap_err(|_| got_body = take(&mut body)))
114 .map_err(|err| {
115 ResponseError::from_http_response_error(
116 err.into_response_error(HttpResponseErrorKind::ReceiveError),
117 x_headers,
118 Some(ResponseErrorKind::ParseResponseError),
119 )
120 .set_response_body_sample(got_body)
121 })?;
122 Ok(Response::from(json_response))
123 }
124
125 pub(super) fn fulfill(self) -> ApiResult<HttpResponse<Vec<u8>>> {
126 let x_headers = XHeaders::from(self.parts());
127 self.0
128 .try_map_body(|mut body| {
129 let mut buf = Vec::new();
130 io_copy(&mut body, &mut buf).map(|_| buf)
131 })
132 .map_err(|err| {
133 ResponseError::from_http_response_error(
134 err.into_response_error(HttpResponseErrorKind::ReceiveError),
135 x_headers,
136 None,
137 )
138 })
139 }
140}
141
142#[cfg(feature = "async")]
143impl Response<AsyncResponseBody> {
144 pub async fn parse_json<T: DeserializeOwned>(self) -> ApiResult<Response<T>> {
146 let x_headers = XHeaders::from(self.parts());
147 let mut got_body = Vec::new();
148 let json_response = self
149 .fulfill()
150 .await?
151 .try_map_body(|mut body| parse_json_from_slice(&body).tap_err(|_| got_body = take(&mut body)))
152 .map_err(|err| {
153 ResponseError::from_http_response_error(
154 err.into_response_error(HttpResponseErrorKind::ReceiveError),
155 x_headers,
156 Some(ResponseErrorKind::ParseResponseError),
157 )
158 .set_response_body_sample(got_body)
159 })?;
160 Ok(Response::from(json_response))
161 }
162
163 pub(super) async fn fulfill(self) -> ApiResult<HttpResponse<Vec<u8>>> {
164 let x_headers = XHeaders::from(self.parts());
165 self.0
166 .try_async_map_body(|mut body| async move {
167 let mut buf = Vec::new();
168 async_io_copy(&mut body, &mut buf).await.map(|_| buf)
169 })
170 .await
171 .map_err(|err| {
172 ResponseError::from_http_response_error(
173 err.into_response_error(HttpResponseErrorKind::ReceiveError),
174 x_headers,
175 None,
176 )
177 })
178 }
179}
180
181fn parse_json_from_slice<'a, T: Deserialize<'a>>(v: &'a [u8]) -> serde_json::Result<T> {
182 if v.is_empty() {
184 serde_json::from_slice(b"{}".as_slice())
185 } else {
186 serde_json::from_slice(v)
187 }
188}
189
190pub type SyncResponse = Response<SyncResponseBody>;
192
193#[cfg(feature = "async")]
195#[cfg_attr(feature = "docs", doc(cfg(feature = "async")))]
196pub type AsyncResponse = Response<AsyncResponseBody>;