resp_result/resp_result/to_response/
axum.rs1#[cfg(all(feature = "tracing", feature = "for-axum"))]
2use trace as tracing;
3
4#[cfg(feature = "for-axum")]
5impl<T, E> axum::response::IntoResponse for crate::RespResult<T, E>
6where
7 T: crate::resp_body::RespBody,
8 E: crate::RespError,
9{
10 #[inline]
11 #[cfg_attr(
12 feature = "tracing",
13 trace::instrument(name = "axum-into-response", skip_all)
14 )]
15 fn into_response(self) -> axum::response::Response {
16 use crate::expect_ext::ExpectExt;
17
18 let respond = super::PrepareRespond::from_resp_result(&self);
19 let mut builder = axum::response::Response::builder().status(respond.status);
20
21 builder
22 .headers_mut()
23 .with_expect("RespResult 构造响应时发生异常")
24 .extend(respond.headers);
25 builder
26 .body(axum::body::boxed(axum::body::Full::from(respond.body)))
27 .with_expect("RespResult 构造响应时发生异常")
28 }
29}
30#[cfg(feature = "for-axum")]
31pub mod axum_respond_part {
32 use std::{convert::Infallible, future::Future};
33
34 use axum::response::{IntoResponse, IntoResponseParts, ResponseParts};
35
36 use crate::{resp_body, Nil, RespError, RespResult};
37
38 pub mod prefab_part_handle {
39 use crate::Nil;
40
41 pub fn no_part<T>(data: T) -> (T, Nil) {
42 (data, Nil)
43 }
44
45 pub fn no_resp<T>(data: T) -> ((), T) {
46 ((), data)
47 }
48 }
49
50 #[inline]
51 pub async fn resp_result_with_respond_part<T, E, F, Fut, R, P, Resp, Part>(
52 handle: F,
53 part_handle: P,
54 ) -> RespResultExtraPart<Resp, E, Part>
55 where
56 F: FnOnce() -> Fut,
58 Fut: Future<Output = R>,
59 R: Into<RespResult<T, E>>,
60 P: FnOnce(T) -> (Resp, Part),
62 Resp: resp_body::RespBody,
63 Part: IntoResponseParts,
64 E: RespError,
65 {
66 let (resp_result, part) = match handle().await.into() {
67 RespResult::Success(data) => {
68 let (resp, part) = part_handle(data);
69 (RespResult::Success(resp), Some(part))
70 }
71 RespResult::Err(err) => (RespResult::Err(err), None),
72 };
73 RespResultExtraPart {
74 inner: resp_result,
75 extra: part,
76 }
77 }
78
79 impl IntoResponseParts for Nil {
80 type Error = Infallible;
81 #[inline]
82 fn into_response_parts(self, res: ResponseParts) -> Result<ResponseParts, Self::Error> {
83 Ok(res)
84 }
85 }
86 #[derive(Debug)]
87 pub struct RespResultExtraPart<T, E, Extra>
88 where
89 T: resp_body::RespBody,
90 E: RespError,
91 Extra: IntoResponseParts,
92 {
93 inner: RespResult<T, E>,
94 extra: Option<Extra>,
95 }
96
97 impl<T, E, Extra> IntoResponse for RespResultExtraPart<T, E, Extra>
98 where
99 T: resp_body::RespBody,
100 E: RespError,
101 Extra: IntoResponseParts,
102 {
103 #[inline]
104 fn into_response(self) -> axum::response::Response {
105 (self.extra, self.inner).into_response()
106 }
107 }
108
109 impl<T, E, Extra> RespResultExtraPart<T, E, Extra>
110 where
111 T: resp_body::RespBody,
112 E: RespError,
113 Extra: IntoResponseParts,
114 {
115 #[inline]
116 pub fn map<R, F>(self, map: F) -> RespResultExtraPart<T, E, R>
117 where
118 F: FnOnce(Extra) -> R,
119 R: IntoResponseParts,
120 {
121 RespResultExtraPart {
122 inner: self.inner,
123 extra: self.extra.map(map),
124 }
125 }
126
127 #[inline]
128 pub fn map_none<F>(self, map: F) -> Self
129 where
130 F: FnOnce() -> Extra,
131 {
132 Self {
133 inner: self.inner,
134 extra: self.extra.or_else(|| Some(map())),
135 }
136 }
137 }
138
139 #[cfg(test)]
140 mod test {
141 use serde::Serialize;
142
143 use crate::RespError;
144
145 use super::resp_result_with_respond_part;
146
147 #[derive(Debug)]
148 struct MockError;
149
150 impl Serialize for MockError {
151 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
152 where
153 S: serde::Serializer,
154 {
155 serializer.serialize_str("Mock Error")
156 }
157 }
158
159 impl RespError for MockError {
160 fn log_message(&self) -> std::borrow::Cow<'_, str> {
161 "Mock Error".into()
162 }
163
164 type ExtraMessage = String;
165
166 fn extra_message(&self) -> Self::ExtraMessage {
167 String::new()
168 }
169 }
170
171 #[tokio::test]
172 async fn test_wrap() {
173 let resp = resp_result_with_respond_part(
174 || async { Result::<_, MockError>::Ok((12i32, [("auth_type", "12345")])) },
175 |(body, part)| (body, part),
176 )
177 .await;
178
179 println!("resp : {:?}", resp);
180 }
181 }
182}