axum_resp_result/resp_result/to_response/
axum.rs

1use 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        // handles
55        F: FnOnce() -> Fut,
56        Fut: Future<Output = R>,
57        R: Into<RespResult<T, E>>,
58        // part into respond and respond part
59        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}