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