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 cookies_raw(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
304 self.req.cookies_raw()
305 }
306
307 #[cfg(feature = "cookies")]
309 #[inline]
310 pub fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
311 self.req.cookie(name)
312 }
313
314 #[cfg(feature = "cookies")]
316 #[inline]
317 pub fn cookie_raw(&self, name: &str) -> Option<Cookie<'static>> {
318 self.req.cookie_raw(name)
319 }
320
321 #[inline]
323 pub fn set_payload(&mut self, payload: Payload) {
324 self.payload = payload;
325 }
326
327 pub fn add_data_container(&mut self, extensions: Rc<Extensions>) {
332 Rc::get_mut(&mut (self.req).inner)
333 .unwrap()
334 .app_data
335 .push(extensions);
336 }
337
338 #[inline]
339 pub(crate) fn push_resource_id(&mut self, id: u16) {
340 self.req.push_resource_id(id);
341 }
342
343 #[inline]
344 pub(crate) fn mark_resource_path(&mut self, is_matched: bool) {
345 self.req.mark_resource_path(is_matched);
346 }
347
348 #[inline]
349 pub(crate) fn resource_id_path(&self) -> &[u16] {
350 self.req.resource_path()
351 }
352
353 #[inline]
355 pub fn guard_ctx(&self) -> GuardContext<'_> {
356 GuardContext { req: self }
357 }
358}
359
360impl Resource for ServiceRequest {
361 type Path = Url;
362
363 #[inline]
364 fn resource_path(&mut self) -> &mut Path<Self::Path> {
365 self.match_info_mut()
366 }
367}
368
369impl HttpMessage for ServiceRequest {
370 type Stream = BoxedPayloadStream;
371
372 #[inline]
373 fn headers(&self) -> &HeaderMap {
374 &self.head().headers
375 }
376
377 #[inline]
378 fn extensions(&self) -> Ref<'_, Extensions> {
379 self.req.extensions()
380 }
381
382 #[inline]
383 fn extensions_mut(&self) -> RefMut<'_, Extensions> {
384 self.req.extensions_mut()
385 }
386
387 #[inline]
388 fn take_payload(&mut self) -> Payload<Self::Stream> {
389 self.payload.take()
390 }
391}
392
393impl fmt::Debug for ServiceRequest {
394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395 writeln!(
396 f,
397 "\nServiceRequest {:?} {}:{}",
398 self.head().version,
399 self.head().method,
400 self.path()
401 )?;
402 if !self.query_string().is_empty() {
403 writeln!(f, " query: ?{:?}", self.query_string())?;
404 }
405 if !self.match_info().is_empty() {
406 writeln!(f, " params: {:?}", self.match_info())?;
407 }
408 writeln!(f, " headers:")?;
409 for (key, val) in self.headers().iter() {
410 writeln!(f, " {:?}: {:?}", key, val)?;
411 }
412 Ok(())
413 }
414}
415
416pub struct ServiceResponse<B = BoxBody> {
418 request: HttpRequest,
419 response: HttpResponse<B>,
420}
421
422impl ServiceResponse<BoxBody> {
423 pub fn from_err<E: Into<Error>>(err: E, request: HttpRequest) -> Self {
425 let response = HttpResponse::from_error(err);
426 ServiceResponse { request, response }
427 }
428}
429
430impl<B> ServiceResponse<B> {
431 pub fn new(request: HttpRequest, response: HttpResponse<B>) -> Self {
433 ServiceResponse { request, response }
434 }
435
436 #[inline]
438 pub fn error_response<E: Into<Error>>(self, err: E) -> ServiceResponse {
439 ServiceResponse::from_err(err, self.request)
440 }
441
442 #[inline]
444 pub fn into_response<B1>(self, response: HttpResponse<B1>) -> ServiceResponse<B1> {
445 ServiceResponse::new(self.request, response)
446 }
447
448 #[inline]
450 pub fn request(&self) -> &HttpRequest {
451 &self.request
452 }
453
454 #[inline]
456 pub fn response(&self) -> &HttpResponse<B> {
457 &self.response
458 }
459
460 #[inline]
462 pub fn response_mut(&mut self) -> &mut HttpResponse<B> {
463 &mut self.response
464 }
465
466 #[inline]
468 pub fn status(&self) -> StatusCode {
469 self.response.status()
470 }
471
472 #[inline]
474 pub fn headers(&self) -> &HeaderMap {
475 self.response.headers()
476 }
477
478 #[inline]
480 pub fn headers_mut(&mut self) -> &mut HeaderMap {
481 self.response.headers_mut()
482 }
483
484 #[inline]
486 pub fn into_parts(self) -> (HttpRequest, HttpResponse<B>) {
487 (self.request, self.response)
488 }
489
490 #[inline]
494 pub fn map_body<F, B2>(self, f: F) -> ServiceResponse<B2>
495 where
496 F: FnOnce(&mut ResponseHead, B) -> B2,
497 {
498 let response = self.response.map_body(f);
499
500 ServiceResponse {
501 response,
502 request: self.request,
503 }
504 }
505
506 #[inline]
507 pub fn map_into_left_body<R>(self) -> ServiceResponse<EitherBody<B, R>> {
508 self.map_body(|_, body| EitherBody::left(body))
509 }
510
511 #[inline]
512 pub fn map_into_right_body<L>(self) -> ServiceResponse<EitherBody<L, B>> {
513 self.map_body(|_, body| EitherBody::right(body))
514 }
515
516 #[inline]
517 pub fn map_into_boxed_body(self) -> ServiceResponse<BoxBody>
518 where
519 B: MessageBody + 'static,
520 {
521 self.map_body(|_, body| body.boxed())
522 }
523
524 #[inline]
526 pub fn into_body(self) -> B {
527 self.response.into_body()
528 }
529}
530
531impl<B> From<ServiceResponse<B>> for HttpResponse<B> {
532 fn from(res: ServiceResponse<B>) -> HttpResponse<B> {
533 res.response
534 }
535}
536
537impl<B> From<ServiceResponse<B>> for Response<B> {
538 fn from(res: ServiceResponse<B>) -> Response<B> {
539 res.response.into()
540 }
541}
542
543impl<B> fmt::Debug for ServiceResponse<B>
544where
545 B: MessageBody,
546 B::Error: Into<Error>,
547{
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 let res = writeln!(
550 f,
551 "\nServiceResponse {:?} {}{}",
552 self.response.head().version,
553 self.response.head().status,
554 self.response.head().reason.unwrap_or(""),
555 );
556 let _ = writeln!(f, " headers:");
557 for (key, val) in self.response.head().headers.iter() {
558 let _ = writeln!(f, " {:?}: {:?}", key, val);
559 }
560 let _ = writeln!(f, " body: {:?}", self.response.body().size());
561 res
562 }
563}
564
565pub struct WebService {
566 rdef: Patterns,
567 name: Option<String>,
568 guards: Vec<Box<dyn Guard>>,
569}
570
571impl WebService {
572 pub fn new<T: IntoPatterns>(path: T) -> Self {
574 WebService {
575 rdef: path.patterns(),
576 name: None,
577 guards: Vec::new(),
578 }
579 }
580
581 pub fn name(mut self, name: &str) -> Self {
585 self.name = Some(name.to_string());
586 self
587 }
588
589 pub fn guard<G: Guard + 'static>(mut self, guard: G) -> Self {
606 self.guards.push(Box::new(guard));
607 self
608 }
609
610 pub fn finish<T, F>(self, service: F) -> impl HttpServiceFactory
612 where
613 F: IntoServiceFactory<T, ServiceRequest>,
614 T: ServiceFactory<
615 ServiceRequest,
616 Config = (),
617 Response = ServiceResponse,
618 Error = Error,
619 InitError = (),
620 > + 'static,
621 {
622 WebServiceImpl {
623 srv: service.into_factory(),
624 rdef: self.rdef,
625 name: self.name,
626 guards: self.guards,
627 }
628 }
629}
630
631struct WebServiceImpl<T> {
632 srv: T,
633 rdef: Patterns,
634 name: Option<String>,
635 guards: Vec<Box<dyn Guard>>,
636}
637
638impl<T> HttpServiceFactory for WebServiceImpl<T>
639where
640 T: ServiceFactory<
641 ServiceRequest,
642 Config = (),
643 Response = ServiceResponse,
644 Error = Error,
645 InitError = (),
646 > + 'static,
647{
648 fn register(mut self, config: &mut AppService) {
649 let guards = if self.guards.is_empty() {
650 None
651 } else {
652 Some(std::mem::take(&mut self.guards))
653 };
654
655 let mut rdef = if config.is_root() || !self.rdef.is_empty() {
656 ResourceDef::new(ensure_leading_slash(self.rdef))
657 } else {
658 ResourceDef::new(self.rdef)
659 };
660
661 if let Some(ref name) = self.name {
662 rdef.set_name(name);
663 }
664
665 config.register_service(rdef, guards, self.srv, None)
666 }
667}
668
669#[macro_export]
693macro_rules! services {
694 () => {()};
695 ($($x:expr),+ $(,)?) => {
696 ($($x,)+)
697 }
698}
699
700macro_rules! service_tuple ({ $($T:ident)+ } => {
702 impl<$($T: HttpServiceFactory),+> HttpServiceFactory for ($($T,)+) {
703 #[allow(non_snake_case)]
704 fn register(self, config: &mut AppService) {
705 let ($($T,)*) = self;
706 $($T.register(config);)+
707 }
708 }
709});
710
711service_tuple! { A }
712service_tuple! { A B }
713service_tuple! { A B C }
714service_tuple! { A B C D }
715service_tuple! { A B C D E }
716service_tuple! { A B C D E F }
717service_tuple! { A B C D E F G }
718service_tuple! { A B C D E F G H }
719service_tuple! { A B C D E F G H I }
720service_tuple! { A B C D E F G H I J }
721service_tuple! { A B C D E F G H I J K }
722service_tuple! { A B C D E F G H I J K L }
723
724#[cfg(test)]
725mod tests {
726 use actix_service::Service;
727 use actix_utils::future::ok;
728
729 use super::*;
730 use crate::{
731 guard, http,
732 test::{self, init_service, TestRequest},
733 web, App,
734 };
735
736 #[actix_rt::test]
737 async fn test_service() {
738 let srv =
739 init_service(
740 App::new().service(web::service("/test").name("test").finish(
741 |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
742 )),
743 )
744 .await;
745 let req = TestRequest::with_uri("/test").to_request();
746 let resp = srv.call(req).await.unwrap();
747 assert_eq!(resp.status(), http::StatusCode::OK);
748
749 let srv =
750 init_service(
751 App::new().service(web::service("/test").guard(guard::Get()).finish(
752 |req: ServiceRequest| ok(req.into_response(HttpResponse::Ok().finish())),
753 )),
754 )
755 .await;
756 let req = TestRequest::with_uri("/test")
757 .method(http::Method::PUT)
758 .to_request();
759 let resp = srv.call(req).await.unwrap();
760 assert_eq!(resp.status(), http::StatusCode::NOT_FOUND);
761 }
762
763 #[allow(deprecated)]
765 #[actix_rt::test]
766 async fn test_service_data() {
767 let srv = init_service(
768 App::new()
769 .data(42u32)
770 .service(
771 web::service("/test")
772 .name("test")
773 .finish(|req: ServiceRequest| {
774 assert_eq!(req.app_data::<web::Data<u32>>().unwrap().as_ref(), &42);
775 ok(req.into_response(HttpResponse::Ok().finish()))
776 }),
777 ),
778 )
779 .await;
780 let req = TestRequest::with_uri("/test").to_request();
781 let resp = srv.call(req).await.unwrap();
782 assert_eq!(resp.status(), http::StatusCode::OK);
783 }
784
785 #[test]
786 fn test_fmt_debug() {
787 let req = TestRequest::get()
788 .uri("/index.html?test=1")
789 .insert_header(("x-test", "111"))
790 .to_srv_request();
791 let s = format!("{:?}", req);
792 assert!(s.contains("ServiceRequest"));
793 assert!(s.contains("test=1"));
794 assert!(s.contains("x-test"));
795
796 let res = HttpResponse::Ok().insert_header(("x-test", "111")).finish();
797 let res = TestRequest::post()
798 .uri("/index.html?test=1")
799 .to_srv_response(res);
800
801 let s = format!("{:?}", res);
802 assert!(s.contains("ServiceResponse"));
803 assert!(s.contains("x-test"));
804 }
805
806 #[actix_rt::test]
807 async fn test_services_macro() {
808 let scoped = services![
809 web::service("/scoped_test1").name("scoped_test1").finish(
810 |req: ServiceRequest| async { Ok(req.into_response(HttpResponse::Ok().finish())) }
811 ),
812 web::resource("/scoped_test2").to(|| async { "test2" }),
813 ];
814
815 let services = services![
816 web::service("/test1")
817 .name("test")
818 .finish(|req: ServiceRequest| async {
819 Ok(req.into_response(HttpResponse::Ok().finish()))
820 }),
821 web::resource("/test2").to(|| async { "test2" }),
822 web::scope("/test3").service(scoped)
823 ];
824
825 let srv = init_service(App::new().service(services)).await;
826
827 let req = TestRequest::with_uri("/test1").to_request();
828 let resp = srv.call(req).await.unwrap();
829 assert_eq!(resp.status(), http::StatusCode::OK);
830
831 let req = TestRequest::with_uri("/test2").to_request();
832 let resp = srv.call(req).await.unwrap();
833 assert_eq!(resp.status(), http::StatusCode::OK);
834
835 let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
836 let resp = srv.call(req).await.unwrap();
837 assert_eq!(resp.status(), http::StatusCode::OK);
838
839 let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
840 let resp = srv.call(req).await.unwrap();
841 assert_eq!(resp.status(), http::StatusCode::OK);
842 }
843
844 #[actix_rt::test]
845 async fn test_services_vec() {
846 let services = vec![
847 web::resource("/test1").to(|| async { "test1" }),
848 web::resource("/test2").to(|| async { "test2" }),
849 ];
850
851 let scoped = vec![
852 web::resource("/scoped_test1").to(|| async { "test1" }),
853 web::resource("/scoped_test2").to(|| async { "test2" }),
854 ];
855
856 let srv = init_service(
857 App::new()
858 .service(services)
859 .service(web::scope("/test3").service(scoped)),
860 )
861 .await;
862
863 let req = TestRequest::with_uri("/test1").to_request();
864 let resp = srv.call(req).await.unwrap();
865 assert_eq!(resp.status(), http::StatusCode::OK);
866
867 let req = TestRequest::with_uri("/test2").to_request();
868 let resp = srv.call(req).await.unwrap();
869 assert_eq!(resp.status(), http::StatusCode::OK);
870
871 let req = TestRequest::with_uri("/test3/scoped_test1").to_request();
872 let resp = srv.call(req).await.unwrap();
873 assert_eq!(resp.status(), http::StatusCode::OK);
874
875 let req = TestRequest::with_uri("/test3/scoped_test2").to_request();
876 let resp = srv.call(req).await.unwrap();
877 assert_eq!(resp.status(), http::StatusCode::OK);
878 }
879
880 #[actix_rt::test]
881 #[should_panic(expected = "called `Option::unwrap()` on a `None` value")]
882 async fn cloning_request_panics() {
883 async fn index(_name: web::Path<(String,)>) -> &'static str {
884 ""
885 }
886
887 let app = test::init_service(
888 App::new()
889 .wrap_fn(|req, svc| {
890 let (req, pl) = req.into_parts();
891 let _req2 = req.clone();
892 let req = ServiceRequest::from_parts(req, pl);
893 svc.call(req)
894 })
895 .route("/", web::get().to(|| async { "" }))
896 .service(web::resource("/resource1/{name}/index.html").route(web::get().to(index))),
897 )
898 .await;
899
900 let req = test::TestRequest::default().to_request();
901 let _res = test::call_service(&app, req).await;
902 }
903
904 #[test]
905 fn define_services_macro_with_multiple_arguments() {
906 let result = services!(1, 2, 3);
907 assert_eq!(result, (1, 2, 3));
908 }
909
910 #[test]
911 fn define_services_macro_with_single_argument() {
912 let result = services!(1);
913 assert_eq!(result, (1,));
914 }
915
916 #[test]
917 fn define_services_macro_with_no_arguments() {
918 let result = services!();
919 let () = result;
920 }
921
922 #[test]
923 fn define_services_macro_with_trailing_comma() {
924 let result = services!(1, 2, 3,);
925 assert_eq!(result, (1, 2, 3));
926 }
927
928 #[test]
929 fn define_services_macro_with_comments_in_arguments() {
930 let result = services!(
931 1, 2, 3 );
935
936 assert_eq!(result, (1, 2, 3));
938 }
939}