1use core::net::SocketAddr;
2
3use crate::{
4 body::ResponseBody,
5 context::WebContext,
6 error::{Error, ErrorStatus},
7 http::{Method, RequestExt, StatusCode, WebRequest, WebResponse},
8};
9
10use super::{FromRequest, Responder};
11
12impl<'a, 'r, C, B, T, E> FromRequest<'a, WebContext<'r, C, B>> for Result<T, E>
13where
14 T: FromRequest<'a, WebContext<'r, C, B>, Error = E>,
15{
16 type Type<'b> = Result<T::Type<'b>, T::Error>;
17 type Error = Error;
18
19 #[inline]
20 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
21 Ok(T::from_request(ctx).await)
22 }
23}
24
25impl<'a, 'r, C, B, T> FromRequest<'a, WebContext<'r, C, B>> for Option<T>
26where
27 T: FromRequest<'a, WebContext<'r, C, B>>,
28{
29 type Type<'b> = Option<T::Type<'b>>;
30 type Error = Error;
31
32 #[inline]
33 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
34 Ok(T::from_request(ctx).await.ok())
35 }
36}
37
38impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for &'a WebContext<'a, C, B>
39where
40 C: 'static,
41 B: 'static,
42{
43 type Type<'b> = &'b WebContext<'b, C, B>;
44 type Error = Error;
45
46 #[inline]
47 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
48 Ok(ctx)
49 }
50}
51
52impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for &'a WebRequest<()> {
53 type Type<'b> = &'b WebRequest<()>;
54 type Error = Error;
55
56 #[inline]
57 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
58 Ok(ctx.req())
59 }
60}
61
62impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for WebRequest<()> {
63 type Type<'b> = WebRequest<()>;
64 type Error = Error;
65
66 #[inline]
67 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
68 Ok(ctx.req().clone())
69 }
70}
71
72impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for &'a RequestExt<()> {
73 type Type<'b> = &'b RequestExt<()>;
74 type Error = Error;
75
76 #[inline]
77 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
78 Ok(ctx.req().body())
79 }
80}
81
82impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for RequestExt<()> {
83 type Type<'b> = RequestExt<()>;
84 type Error = Error;
85
86 #[inline]
87 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
88 Ok(ctx.req().body().clone())
89 }
90}
91
92impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for &'a SocketAddr {
93 type Type<'b> = &'b SocketAddr;
94 type Error = Error;
95
96 #[inline]
97 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
98 Ok(ctx.req().body().socket_addr())
99 }
100}
101
102impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for SocketAddr {
103 type Type<'b> = SocketAddr;
104 type Error = Error;
105
106 #[inline]
107 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
108 Ok(*ctx.req().body().socket_addr())
109 }
110}
111
112impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for &'a Method {
113 type Type<'b> = &'b Method;
114 type Error = Error;
115
116 #[inline]
117 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
118 Ok(ctx.req().method())
119 }
120}
121
122impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for Method {
123 type Type<'b> = Method;
124 type Error = Error;
125
126 #[inline]
127 async fn from_request(ctx: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
128 Ok(ctx.req().method().clone())
129 }
130}
131
132impl<'a, 'r, C, B> FromRequest<'a, WebContext<'r, C, B>> for () {
133 type Type<'b> = ();
134 type Error = Error;
135
136 #[inline]
137 async fn from_request(_: &'a WebContext<'r, C, B>) -> Result<Self, Self::Error> {
138 Ok(())
139 }
140}
141
142impl<'r, C, B, T, Res, Err, E> Responder<WebContext<'r, C, B>> for Result<T, E>
143where
144 T: for<'r2> Responder<WebContext<'r2, C, B>, Response = Res, Error = Err>,
145 Error: From<E> + From<Err>,
146{
147 type Response = Res;
148 type Error = Error;
149
150 #[inline]
151 async fn respond(self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
152 self?.respond(ctx).await.map_err(Into::into)
153 }
154}
155
156impl<'r, C, B, ResB> Responder<WebContext<'r, C, B>> for WebResponse<ResB> {
157 type Response = WebResponse<ResB>;
158 type Error = Error;
159
160 #[inline]
161 async fn respond(self, _: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
162 Ok(self)
163 }
164}
165
166impl<'r, C, B> Responder<WebContext<'r, C, B>> for Error {
167 type Response = WebResponse;
168 type Error = Error;
169
170 #[inline]
171 async fn respond(self, _: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
172 Err(self)
173 }
174}
175
176impl<'r, C, B> Responder<WebContext<'r, C, B>> for ErrorStatus {
177 type Response = WebResponse;
178 type Error = Error;
179
180 #[inline]
181 async fn respond(self, _: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
182 Err(Error::from(self))
183 }
184}
185
186impl<'r, C, B> Responder<WebContext<'r, C, B>> for StatusCode {
187 type Response = WebResponse;
188 type Error = Error;
189
190 async fn respond(self, ctx: WebContext<'r, C, B>) -> Result<Self::Response, Self::Error> {
191 let res = ctx.into_response(ResponseBody::empty());
192 Responder::<WebContext<'r, C, B>>::map(self, res)
193 }
194
195 fn map(self, mut res: Self::Response) -> Result<Self::Response, Self::Error> {
196 *res.status_mut() = self;
197 Ok(res)
198 }
199}
200
201#[cfg(feature = "serde")]
203const _: () = {
204 crate::error::error_from_service!(serde::de::value::Error);
205 crate::error::forward_blank_bad_request!(serde::de::value::Error);
206};
207
208#[cfg(test)]
209mod test {
210 use xitca_unsafe_collection::futures::NowOrPanic;
211
212 use crate::http::header::{CONTENT_TYPE, COOKIE, HeaderMap, HeaderValue};
213
214 use super::*;
215
216 #[test]
217 fn extract_default_impls() {
218 let mut req = WebContext::new_test(());
219 let req = req.as_web_ctx();
220
221 Option::<()>::from_request(&req).now_or_panic().unwrap().unwrap();
222
223 Result::<(), Error>::from_request(&req).now_or_panic().unwrap().unwrap();
224
225 <&WebContext<'_>>::from_request(&req).now_or_panic().unwrap();
226
227 <()>::from_request(&req).now_or_panic().unwrap();
228 }
229
230 #[test]
231 fn respond_chain() {
232 let mut req = WebContext::new_test(());
233 let mut req = req.as_web_ctx();
234
235 let mut headers = HeaderMap::new();
236 headers.insert(COOKIE, HeaderValue::from_static("none"));
237
238 let check_res = |res: WebResponse| {
239 assert_eq!(res.status(), StatusCode::ACCEPTED);
240 assert_eq!(res.headers().get(COOKIE).unwrap().to_str().unwrap(), "none");
241 assert_eq!(
242 res.headers().get(CONTENT_TYPE).unwrap().to_str().unwrap(),
243 "text/plain; charset=utf-8"
244 );
245 };
246
247 let res = (StatusCode::ACCEPTED, headers.clone(), "hello,world!")
248 .respond(req.reborrow())
249 .now_or_panic()
250 .unwrap();
251 check_res(res);
252
253 let res = ("hello,world!", StatusCode::ACCEPTED, headers.clone())
254 .respond(req.reborrow())
255 .now_or_panic()
256 .unwrap();
257 check_res(res);
258
259 let res = (headers, "hello,world!", StatusCode::ACCEPTED)
260 .respond(req)
261 .now_or_panic()
262 .unwrap();
263 check_res(res);
264 }
265}