1use std::{
2 cell::{Ref, RefMut},
3 fmt, net,
4 rc::Rc,
5};
6
7use actix_http::{
8 body::{BoxBody, EitherBody, MessageBody},
9 header::HeaderMap,
10 BoxedPayloadStream, Extensions, HttpMessage, Method, Payload, RequestHead, Response,
11 ResponseHead, StatusCode, Uri, Version,
12};
13use actix_router::{IntoPatterns, Path, Patterns, Resource, ResourceDef, Url};
14use actix_service::{
15 boxed::{BoxService, BoxServiceFactory},
16 IntoServiceFactory, ServiceFactory,
17};
18#[cfg(feature = "cookies")]
19use cookie::{Cookie, ParseError as CookieParseError};
20
21use crate::{
22 config::{AppConfig, AppService},
23 dev::ensure_leading_slash,
24 guard::{Guard, GuardContext},
25 info::ConnectionInfo,
26 rmap::ResourceMap,
27 Error, FromRequest, HttpRequest, HttpResponse,
28};
29
30pub(crate) type BoxedHttpService = BoxService<ServiceRequest, ServiceResponse<BoxBody>, Error>;
31pub(crate) type BoxedHttpServiceFactory =
32 BoxServiceFactory<(), ServiceRequest, ServiceResponse<BoxBody>, Error, ()>;
33
34pub trait HttpServiceFactory {
35 fn register(self, config: &mut AppService);
36}
37
38impl<T: HttpServiceFactory> HttpServiceFactory for Vec<T> {
39 fn register(self, config: &mut AppService) {
40 self.into_iter()
41 .for_each(|factory| factory.register(config));
42 }
43}
44
45pub(crate) trait AppServiceFactory {
46 fn register(&mut self, config: &mut AppService);
47}
48
49pub(crate) struct ServiceFactoryWrapper<T> {
50 factory: Option<T>,
51}
52
53impl<T> ServiceFactoryWrapper<T> {
54 pub fn new(factory: T) -> Self {
55 Self {
56 factory: Some(factory),
57 }
58 }
59}
60
61impl<T> AppServiceFactory for ServiceFactoryWrapper<T>
62where
63 T: HttpServiceFactory,
64{
65 fn register(&mut self, config: &mut AppService) {
66 if let Some(item) = self.factory.take() {
67 item.register(config)
68 }
69 }
70}
71
72pub struct ServiceRequest {
76 req: HttpRequest,
77 payload: Payload,
78}
79
80impl ServiceRequest {
81 pub(crate) fn new(req: HttpRequest, payload: Payload) -> Self {
83 Self { req, payload }
84 }
85
86 #[inline]
88 pub fn into_parts(self) -> (HttpRequest, Payload) {
89 (self.req, self.payload)
90 }
91
92 #[inline]
94 pub fn parts_mut(&mut self) -> (&mut HttpRequest, &mut Payload) {
95 (&mut self.req, &mut self.payload)
96 }
97
98 #[inline]
100 pub fn parts(&self) -> (&HttpRequest, &Payload) {
101 (&self.req, &self.payload)
102 }
103
104 #[inline]
106 pub fn request(&self) -> &HttpRequest {
107 &self.req
108 }
109
110 pub fn extract<T>(&mut self) -> <T as FromRequest>::Future
129 where
130 T: FromRequest,
131 {
132 T::from_request(&self.req, &mut self.payload)
133 }
134
135 pub fn from_parts(req: HttpRequest, payload: Payload) -> Self {
137 #[cfg(debug_assertions)]
138 if Rc::strong_count(&req.inner) > 1 {
139 log::warn!("Cloning an `HttpRequest` might cause panics.");
140 }
141
142 Self { req, payload }
143 }
144
145 #[inline]
147 pub fn from_request(req: HttpRequest) -> Self {
148 ServiceRequest {
149 req,
150 payload: Payload::None,
151 }
152 }
153
154 #[inline]
156 pub fn into_response<B, R: Into<Response<B>>>(self, res: R) -> ServiceResponse<B> {
157 let res = HttpResponse::from(res.into());
158 ServiceResponse::new(self.req, res)
159 }
160
161 #[inline]
163 pub fn error_response<E: Into<Error>>(self, err: E) -> ServiceResponse {
164 let res = HttpResponse::from_error(err.into());
165 ServiceResponse::new(self.req, res)
166 }
167
168 #[inline]
170 pub fn head(&self) -> &RequestHead {
171 self.req.head()
172 }
173
174 #[inline]
176 pub fn head_mut(&mut self) -> &mut RequestHead {
177 self.req.head_mut()
178 }
179
180 #[inline]
182 pub fn uri(&self) -> &Uri {
183 &self.head().uri
184 }
185
186 #[inline]
188 pub fn method(&self) -> &Method {
189 &self.head().method
190 }
191
192 #[inline]
194 pub fn version(&self) -> Version {
195 self.head().version
196 }
197
198 #[inline]
200 pub fn headers(&self) -> &HeaderMap {
201 &self.head().headers
202 }
203
204 #[inline]
206 pub fn headers_mut(&mut self) -> &mut HeaderMap {
207 &mut self.head_mut().headers
208 }
209
210 #[inline]
212 pub fn path(&self) -> &str {
213 self.head().uri.path()
214 }
215
216 #[inline]
218 pub fn query_string(&self) -> &str {
219 self.req.query_string()
220 }
221
222 #[inline]
228 pub fn peer_addr(&self) -> Option<net::SocketAddr> {
229 self.head().peer_addr
230 }
231
232 #[inline]
234 pub fn connection_info(&self) -> Ref<'_, ConnectionInfo> {
235 self.req.connection_info()
236 }
237
238 #[inline]
240 pub fn match_info(&self) -> &Path<Url> {
241 self.req.match_info()
242 }
243
244 #[inline]
246 pub fn match_info_mut(&mut self) -> &mut Path<Url> {
247 self.req.match_info_mut()
248 }
249
250 #[inline]
252 pub fn match_name(&self) -> Option<&str> {
253 self.req.match_name()
254 }
255
256 #[inline]
258 pub fn match_pattern(&self) -> Option<String> {
259 self.req.match_pattern()
260 }
261
262 #[inline]
265 pub fn resource_map(&self) -> &ResourceMap {
266 self.req.resource_map()
267 }
268
269 #[inline]
271 pub fn app_config(&self) -> &AppConfig {
272 self.req.app_config()
273 }
274
275 #[inline]
277 pub fn app_data<T: 'static>(&self) -> Option<&T> {
278 for container in self.req.inner.app_data.iter().rev() {
279 if let Some(data) = container.get::<T>() {
280 return Some(data);
281 }
282 }
283
284 None
285 }
286
287 #[inline]
289 pub fn conn_data<T: 'static>(&self) -> Option<&T> {
290 self.req.conn_data()
291 }
292
293 #[cfg(feature = "cookies")]
295 #[inline]
296 pub fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
297 self.req.cookies()
298 }
299
300 #[cfg(feature = "cookies")]
302 #[inline]
303 pub fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
304 self.req.cookie(name)
305 }
306
307 #[inline]
309 pub fn set_payload(&mut self, payload: Payload) {
310 self.payload = payload;
311 }
312
313 pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
318 Rc::get_mut(&mut (self.req).inner)
319 .unwrap()
320 .app_data
321 .push(extensions);
322 }
323
324 #[inline]
326 pub fn guard_ctx(&self) -> GuardContext<'_> {
327 GuardContext { req: self }
328 }
329}
330
331impl Resource for ServiceRequest {
332 type Path = Url;
333
334 #[inline]
335 fn resource_path(&mut self) -> &mut Path<Self::Path> {
336 self.match_info_mut()
337 }
338}
339
340impl HttpMessage for ServiceRequest {
341 type Stream = BoxedPayloadStream;
342
343 #[inline]
344 fn headers(&self) -> &HeaderMap {
345 &self.head().headers
346 }
347
348 #[inline]
349 fn extensions(&self) -> Ref<'_, Extensions> {
350 self.req.extensions()
351 }
352
353 #[inline]
354 fn extensions_mut(&self) -> RefMut<'_, Extensions> {
355 self.req.extensions_mut()
356 }
357
358 #[inline]
359 fn take_payload(&mut self) -> Payload<Self::Stream> {
360 self.payload.take()
361 }
362}
363
364impl fmt::Debug for ServiceRequest {
365 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366 writeln!(
367 f,
368 "\nServiceRequest {:?} {}:{}",
369 self.head().version,
370 self.head().method,
371 self.path()
372 )?;
373 if !self.query_string().is_empty() {
374 writeln!(f, " query: ?{:?}", self.query_string())?;
375 }
376 if !self.match_info().is_empty() {
377 writeln!(f, " params: {:?}", self.match_info())?;
378 }
379 writeln!(f, " headers:")?;
380 for (key, val) in self.headers().iter() {
381 writeln!(f, " {:?}: {:?}", key, val)?;
382 }
383 Ok(())
384 }
385}
386
387pub struct ServiceResponse<B = BoxBody> {
389 request: HttpRequest,
390 response: HttpResponse<B>,
391}
392
393impl ServiceResponse<BoxBody> {
394 pub fn from_err<E: Into<Error>>(err: E, request: HttpRequest) -> Self {
396 let response = HttpResponse::from_error(err);
397 ServiceResponse { request, response }
398 }
399}
400
401impl<B> ServiceResponse<B> {
402 pub fn new(request: HttpRequest, response: HttpResponse<B>) -> Self {
404 ServiceResponse { request, response }
405 }
406
407 #[inline]
409 pub fn error_response<E: Into<Error>>(self, err: E) -> ServiceResponse {
410 ServiceResponse::from_err(err, self.request)
411 }
412
413 #[inline]
415 pub fn into_response<B1>(self, response: HttpResponse<B1>) -> ServiceResponse<B1> {
416 ServiceResponse::new(self.request, response)
417 }
418
419 #[inline]
421 pub fn request(&self) -> &HttpRequest {
422 &self.request
423 }
424
425 #[inline]
427 pub fn response(&self) -> &HttpResponse<B> {
428 &self.response
429 }
430
431 #[inline]
433 pub fn response_mut(&mut self) -> &mut HttpResponse<B> {
434 &mut self.response
435 }
436
437 #[inline]
439 pub fn status(&self) -> StatusCode {
440 self.response.status()
441 }
442
443 #[inline]
445 pub fn headers(&self) -> &HeaderMap {
446 self.response.headers()
447 }
448
449 #[inline]
451 pub fn headers_mut(&mut self) -> &mut HeaderMap {
452 self.response.headers_mut()
453 }
454
455 #[inline]
457 pub fn into_parts(self) -> (HttpRequest, HttpResponse<B>) {
458 (self.request, self.response)
459 }
460
461 #[inline]
465 pub fn map_body<F, B2>(self, f: F) -> ServiceResponse<B2>
466 where
467 F: FnOnce(&mut ResponseHead, B) -> B2,
468 {
469 let response = self.response.map_body(f);
470
471 ServiceResponse {
472 response,
473 request: self.request,
474 }
475 }
476
477 #[inline]
478 pub fn map_into_left_body<R>(self) -> ServiceResponse<EitherBody<B, R>> {
479 self.map_body(|_, body| EitherBody::left(body))
480 }
481
482 #[inline]
483 pub fn map_into_right_body<L>(self) -> ServiceResponse<EitherBody<L, B>> {
484 self.map_body(|_, body| EitherBody::right(body))
485 }
486
487 #[inline]
488 pub fn map_into_boxed_body(self) -> ServiceResponse<BoxBody>
489 where
490 B: MessageBody + 'static,
491 {
492 self.map_body(|_, body| body.boxed())
493 }
494
495 #[inline]
497 pub fn into_body(self) -> B {
498 self.response.into_body()
499 }
500}
501
502impl<B> From<ServiceResponse<B>> for HttpResponse<B> {
503 fn from(res: ServiceResponse<B>) -> HttpResponse<B> {
504 res.response
505 }
506}
507
508impl<B> From<ServiceResponse<B>> for Response<B> {
509 fn from(res: ServiceResponse<B>) -> Response<B> {
510 res.response.into()
511 }
512}
513
514impl<B> fmt::Debug for ServiceResponse<B>
515where
516 B: MessageBody,
517 B::Error: Into<Error>,
518{
519 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520 let res = writeln!(
521 f,
522 "\nServiceResponse {:?} {}{}",
523 self.response.head().version,
524 self.response.head().status,
525 self.response.head().reason.unwrap_or(""),
526 );
527 let _ = writeln!(f, " headers:");
528 for (key, val) in self.response.head().headers.iter() {
529 let _ = writeln!(f, " {:?}: {:?}", key, val);
530 }
531 let _ = writeln!(f, " body: {:?}", self.response.body().size());
532 res
533 }
534}
535
536pub struct WebService {
537 rdef: Patterns,
538 name: Option<String>,
539 guards: Vec<Box<dyn Guard>>,
540}
541
542impl WebService {
543 pub fn new<T: IntoPatterns>(path: T) -> Self {
545 WebService {
546 rdef: path.patterns(),
547 name: None,
548 guards: Vec::new(),
549 }
550 }
551
552 pub fn name(mut self, name: &str) -> Self {
556 self.name = Some(name.to_string());
557 self
558 }
559
560 pub fn guard<G: Guard + 'static>(mut self, guard: G) -> Self {
577 self.guards.push(Box::new(guard));
578 self
579 }
580
581 pub fn finish<T, F>(self, service: F) -> impl HttpServiceFactory
583 where
584 F: IntoServiceFactory<T, ServiceRequest>,
585 T: ServiceFactory<
586 ServiceRequest,
587 Config = (),
588 Response = ServiceResponse,
589 Error = Error,
590 InitError = (),
591 > + 'static,
592 {
593 WebServiceImpl {
594 srv: service.into_factory(),
595 rdef: self.rdef,
596 name: self.name,
597 guards: self.guards,
598 }
599 }
600}
601
602struct WebServiceImpl<T> {
603 srv: T,
604 rdef: Patterns,
605 name: Option<String>,
606 guards: Vec<Box<dyn Guard>>,
607}
608
609impl<T> HttpServiceFactory for WebServiceImpl<T>
610where
611 T: ServiceFactory<
612 ServiceRequest,
613 Config = (),
614 Response = ServiceResponse,
615 Error = Error,
616 InitError = (),
617 > + 'static,
618{
619 fn register(mut self, config: &mut AppService) {
620 let guards = if self.guards.is_empty() {
621 None
622 } else {
623 Some(std::mem::take(&mut self.guards))
624 };
625
626 let mut rdef = if config.is_root() || !self.rdef.is_empty() {
627 ResourceDef::new(ensure_leading_slash(self.rdef))
628 } else {
629 ResourceDef::new(self.rdef)
630 };
631
632 if let Some(ref name) = self.name {
633 rdef.set_name(name);
634 }
635
636 config.register_service(rdef, guards, self.srv, None)
637 }
638}
639
640#[macro_export]
664macro_rules! services {
665 () => {()};
666 ($($x:expr),+ $(,)?) => {
667 ($($x,)+)
668 }
669}
670
671macro_rules! service_tuple ({ $($T:ident)+ } => {
673 impl<$($T: HttpServiceFactory),+> HttpServiceFactory for ($($T,)+) {
674 #[allow(non_snake_case)]
675 fn register(self, config: &mut AppService) {
676 let ($($T,)*) = self;
677 $($T.register(config);)+
678 }
679 }
680});
681
682service_tuple! { A }
683service_tuple! { A B }
684service_tuple! { A B C }
685service_tuple! { A B C D }
686service_tuple! { A B C D E }
687service_tuple! { A B C D E F }
688service_tuple! { A B C D E F G }
689service_tuple! { A B C D E F G H }
690service_tuple! { A B C D E F G H I }
691service_tuple! { A B C D E F G H I J }
692service_tuple! { A B C D E F G H I J K }
693service_tuple! { A B C D E F G H I J K L }
694
695#[cfg(test)]
696mod tests {
697 use actix_service::Service;
698 use actix_utils::future::ok;
699
700 use super::*;
701 use crate::{
702 guard, http,
703 test::{self, init_service, TestRequest},
704 web, App,
705 };
706
707 #[actix_rt::test]
708 async fn test_service() {
709 let srv =
710 init_service(
711 App::new().service(web::service("/test").name("test").finish(
712 |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
713 )),
714 )
715 .await;
716 let req = TestRequest::with_uri("/test").to_request();
717 let resp = srv.call(req).await.unwrap();
718 assert_eq!(resp.status(), http::StatusCode::OK);
719
720 let srv =
721 init_service(
722 App::new().service(web::service("/test").guard(guard::Get()).finish(
723 |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
724 )),
725 )
726 .await;
727 let req = TestRequest::with_uri("/test")
728 .method(http::Method::PUT)
729 .to_request();
730 let resp = srv.call(req).await.unwrap();
731 assert_eq!(resp.status(), http::StatusCode::NOT_FOUND);
732 }
733
734 #[allow(deprecated)]
736 #[actix_rt::test]
737 async fn test_service_data() {
738 let srv = init_service(
739 App::new()
740 .data(42u32)
741 .service(
742 web::service("/test")
743 .name("test")
744 .finish(|req: ServiceRequest| {
745 assert_eq!(req.app_data::<web::Data<u32>>().unwrap().as_ref(), &42);
746 ok(req.into_response(HttpResponse::Ok().finish()))
747 }),
748 ),
749 )
750 .await;
751 let req = TestRequest::with_uri("/test").to_request();
752 let resp = srv.call(req).await.unwrap();
753 assert_eq!(resp.status(), http::StatusCode::OK);
754 }
755
756 #[test]
757 fn test_fmt_debug() {
758 let req = TestRequest::get()
759 .uri("/index.html?test=1")
760 .insert_header(("x-test", "111"))
761 .to_srv_request();
762 let s = format!("{:?}", req);
763 assert!(s.contains("ServiceRequest"));
764 assert!(s.contains("test=1"));
765 assert!(s.contains("x-test"));
766
767 let res = HttpResponse::Ok().insert_header(("x-test", "111")).finish();
768 let res = TestRequest::post()
769 .uri("/index.html?test=1")
770 .to_srv_response(res);
771
772 let s = format!("{:?}", res);
773 assert!(s.contains("ServiceResponse"));
774 assert!(s.contains("x-test"));
775 }
776
777 #[actix_rt::test]
778 async fn test_services_macro() {
779 let scoped = services![
780 web::service("/scoped_test1").name("scoped_test1").finish(
781 |req: ServiceRequest| async { Ok(req.into_response(HttpResponse::Ok().finish())) }
782 ),
783 web::resource("/scoped_test2").to(|| async { "test2" }),
784 ];
785
786 let services = services![
787 web::service("/test1")
788 .name("test")
789 .finish(|req: ServiceRequest| async {
790 Ok(req.into_response(HttpResponse::Ok().finish()))
791 }),
792 web::resource("/test2").to(|| async { "test2" }),
793 web::scope("/test3").service(scoped)
794 ];
795
796 let srv = init_service(App::new().service(services)).await;
797
798 let req = TestRequest::with_uri("/test1").to_request();
799 let resp = srv.call(req).await.unwrap();
800 assert_eq!(resp.status(), http::StatusCode::OK);
801
802 let req = TestRequest::with_uri("/test2").to_request();
803 let resp = srv.call(req).await.unwrap();
804 assert_eq!(resp.status(), http::StatusCode::OK);
805
806 let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
807 let resp = srv.call(req).await.unwrap();
808 assert_eq!(resp.status(), http::StatusCode::OK);
809
810 let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
811 let resp = srv.call(req).await.unwrap();
812 assert_eq!(resp.status(), http::StatusCode::OK);
813 }
814
815 #[actix_rt::test]
816 async fn test_services_vec() {
817 let services = vec![
818 web::resource("/test1").to(|| async { "test1" }),
819 web::resource("/test2").to(|| async { "test2" }),
820 ];
821
822 let scoped = vec![
823 web::resource("/scoped_test1").to(|| async { "test1" }),
824 web::resource("/scoped_test2").to(|| async { "test2" }),
825 ];
826
827 let srv = init_service(
828 App::new()
829 .service(services)
830 .service(web::scope("/test3").service(scoped)),
831 )
832 .await;
833
834 let req = TestRequest::with_uri("/test1").to_request();
835 let resp = srv.call(req).await.unwrap();
836 assert_eq!(resp.status(), http::StatusCode::OK);
837
838 let req = TestRequest::with_uri("/test2").to_request();
839 let resp = srv.call(req).await.unwrap();
840 assert_eq!(resp.status(), http::StatusCode::OK);
841
842 let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
843 let resp = srv.call(req).await.unwrap();
844 assert_eq!(resp.status(), http::StatusCode::OK);
845
846 let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
847 let resp = srv.call(req).await.unwrap();
848 assert_eq!(resp.status(), http::StatusCode::OK);
849 }
850
851 #[actix_rt::test]
852 #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
853 async fn cloning_request_panics() {
854 async fn index(_name: web::Path<(String,)>) -> &'static str {
855 ""
856 }
857
858 let app = test::init_service(
859 App::new()
860 .wrap_fn(|req, svc| {
861 let (req, pl) = req.into_parts();
862 let _req2 = req.clone();
863 let req = ServiceRequest::from_parts(req, pl);
864 svc.call(req)
865 })
866 .route("/", web::get().to(|| async { "" }))
867 .service(web::resource("/resource1/{name}/index.html").route(web::get().to(index))),
868 )
869 .await;
870
871 let req = test::TestRequest::default().to_request();
872 let _res = test::call_service(&app, req).await;
873 }
874
875 #[test]
876 fn define_services_macro_with_multiple_arguments() {
877 let result = services!(1, 2, 3);
878 assert_eq!(result, (1, 2, 3));
879 }
880
881 #[test]
882 fn define_services_macro_with_single_argument() {
883 let result = services!(1);
884 assert_eq!(result, (1,));
885 }
886
887 #[test]
888 fn define_services_macro_with_no_arguments() {
889 let result = services!();
890 let () = result;
891 }
892
893 #[test]
894 fn define_services_macro_with_trailing_comma() {
895 let result = services!(1, 2, 3,);
896 assert_eq!(result, (1, 2, 3));
897 }
898
899 #[test]
900 fn define_services_macro_with_comments_in_arguments() {
901 let result = services!(
902 1, 2, 3 );
906
907 assert_eq!(result, (1, 2, 3));
909 }
910}