1use std::{
2 any::Any,
3 cmp, fmt,
4 future::Future,
5 io,
6 marker::PhantomData,
7 net,
8 sync::{Arc, Mutex},
9 time::Duration,
10};
11
12#[cfg(feature = "__tls")]
13use actix_http::TlsAcceptorConfig;
14use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
15use actix_server::{Server, ServerBuilder};
16use actix_service::{
17 map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _,
18};
19#[cfg(feature = "openssl")]
20use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder};
21
22use crate::{config::AppConfig, Error};
23
24struct Socket {
25 scheme: &'static str,
26 addr: net::SocketAddr,
27}
28
29struct Config {
30 host: Option<String>,
31 keep_alive: KeepAlive,
32 tcp_nodelay: Option<bool>,
33 client_request_timeout: Duration,
34 client_disconnect_timeout: Duration,
35 h1_allow_half_closed: bool,
36 h2_initial_window_size: Option<u32>,
37 h2_initial_connection_window_size: Option<u32>,
38 #[allow(dead_code)] tls_handshake_timeout: Option<Duration>,
40}
41
42#[must_use]
74pub struct HttpServer<F, I, S, B>
75where
76 F: Fn() -> I + Send + Clone + 'static,
77 I: IntoServiceFactory<S, Request>,
78 S: ServiceFactory<Request, Config = AppConfig>,
79 S::Error: Into<Error>,
80 S::InitError: fmt::Debug,
81 S::Response: Into<Response<B>>,
82 B: MessageBody,
83{
84 pub(super) factory: F,
85 config: Arc<Mutex<Config>>,
86 backlog: u32,
87 sockets: Vec<Socket>,
88 builder: ServerBuilder,
89 #[allow(clippy::type_complexity)]
90 on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
91 _phantom: PhantomData<(S, B)>,
92}
93
94impl<F, I, S, B> HttpServer<F, I, S, B>
95where
96 F: Fn() -> I + Send + Clone + 'static,
97 I: IntoServiceFactory<S, Request>,
98
99 S: ServiceFactory<Request, Config = AppConfig> + 'static,
100 S::Error: Into<Error> + 'static,
101 S::InitError: fmt::Debug,
102 S::Response: Into<Response<B>> + 'static,
103 <S::Service as Service<Request>>::Future: 'static,
104 S::Service: 'static,
105
106 B: MessageBody + 'static,
107{
108 pub fn new(factory: F) -> Self {
116 HttpServer {
117 factory,
118 config: Arc::new(Mutex::new(Config {
119 host: None,
120 keep_alive: KeepAlive::default(),
121 tcp_nodelay: None,
122 client_request_timeout: Duration::from_secs(5),
123 client_disconnect_timeout: Duration::from_secs(1),
124 h1_allow_half_closed: true,
125 h2_initial_window_size: None,
126 h2_initial_connection_window_size: None,
127 tls_handshake_timeout: None,
128 })),
129 backlog: 1024,
130 sockets: Vec::new(),
131 builder: ServerBuilder::default(),
132 on_connect_fn: None,
133 _phantom: PhantomData,
134 }
135 }
136
137 pub fn workers(mut self, num: usize) -> Self {
152 self.builder = self.builder.workers(num);
153 self
154 }
155
156 pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
160 self.config.lock().unwrap().keep_alive = val.into();
161 self
162 }
163
164 pub fn tcp_nodelay(self, enabled: bool) -> Self {
169 self.config.lock().unwrap().tcp_nodelay = Some(enabled);
170 self
171 }
172
173 pub fn backlog(mut self, backlog: u32) -> Self {
183 self.backlog = backlog;
184 self.builder = self.builder.backlog(backlog);
185 self
186 }
187
188 pub fn max_connections(mut self, num: usize) -> Self {
195 self.builder = self.builder.max_concurrent_connections(num);
196 self
197 }
198
199 #[allow(unused_variables)]
206 pub fn max_connection_rate(self, num: usize) -> Self {
207 #[cfg(feature = "__tls")]
208 actix_tls::accept::max_concurrent_tls_connect(num);
209 self
210 }
211
212 pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
218 self.builder = self.builder.worker_max_blocking_threads(num);
219 self
220 }
221
222 pub fn client_request_timeout(self, dur: Duration) -> Self {
231 self.config.lock().unwrap().client_request_timeout = dur;
232 self
233 }
234
235 #[doc(hidden)]
236 #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
237 pub fn client_timeout(self, dur: Duration) -> Self {
238 self.client_request_timeout(dur)
239 }
240
241 pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
250 self.config.lock().unwrap().client_disconnect_timeout = dur;
251 self
252 }
253
254 #[cfg(feature = "__tls")]
261 pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
262 self.config
263 .lock()
264 .unwrap()
265 .tls_handshake_timeout
266 .replace(dur);
267
268 self
269 }
270
271 #[doc(hidden)]
272 #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
273 pub fn client_shutdown(self, dur: u64) -> Self {
274 self.client_disconnect_timeout(Duration::from_millis(dur))
275 }
276
277 pub fn h1_allow_half_closed(self, allow: bool) -> Self {
285 self.config.lock().unwrap().h1_allow_half_closed = allow;
286 self
287 }
288
289 #[cfg(feature = "http2")]
296 pub fn h2_initial_window_size(self, size: u32) -> Self {
297 self.config.lock().unwrap().h2_initial_window_size = Some(size);
298 self
299 }
300
301 #[cfg(feature = "http2")]
308 pub fn h2_initial_connection_window_size(self, size: u32) -> Self {
309 self.config
310 .lock()
311 .unwrap()
312 .h2_initial_connection_window_size = Some(size);
313 self
314 }
315
316 pub fn on_connect<CB>(mut self, f: CB) -> HttpServer<F, I, S, B>
335 where
336 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
337 {
338 self.on_connect_fn = Some(Arc::new(f));
339 self
340 }
341
342 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
349 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
350 self
351 }
352
353 pub fn system_exit(mut self) -> Self {
357 self.builder = self.builder.system_exit();
358 self
359 }
360
361 pub fn disable_signals(mut self) -> Self {
363 self.builder = self.builder.disable_signals();
364 self
365 }
366
367 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
391 where
392 Fut: Future<Output = ()> + Send + 'static,
393 {
394 self.builder = self.builder.shutdown_signal(shutdown_signal);
395 self
396 }
397
398 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
405 self.builder = self.builder.shutdown_timeout(sec);
406 self
407 }
408
409 pub fn addrs(&self) -> Vec<net::SocketAddr> {
411 self.sockets.iter().map(|s| s.addr).collect()
412 }
413
414 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
420 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
421 }
422
423 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
470 let sockets = bind_addrs(addrs, self.backlog)?;
471
472 for lst in sockets {
473 self = self.listen(lst)?;
474 }
475
476 Ok(self)
477 }
478
479 #[cfg(feature = "http2")]
484 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
485 let sockets = bind_addrs(addrs, self.backlog)?;
486
487 for lst in sockets {
488 self = self.listen_auto_h2c(lst)?;
489 }
490
491 Ok(self)
492 }
493
494 #[cfg(feature = "rustls-0_20")]
501 pub fn bind_rustls<A: net::ToSocketAddrs>(
502 mut self,
503 addrs: A,
504 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
505 ) -> io::Result<Self> {
506 let sockets = bind_addrs(addrs, self.backlog)?;
507 for lst in sockets {
508 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
509 }
510 Ok(self)
511 }
512
513 #[cfg(feature = "rustls-0_21")]
520 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
521 mut self,
522 addrs: A,
523 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
524 ) -> io::Result<Self> {
525 let sockets = bind_addrs(addrs, self.backlog)?;
526 for lst in sockets {
527 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
528 }
529 Ok(self)
530 }
531
532 #[cfg(feature = "rustls-0_22")]
539 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
540 mut self,
541 addrs: A,
542 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
543 ) -> io::Result<Self> {
544 let sockets = bind_addrs(addrs, self.backlog)?;
545 for lst in sockets {
546 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
547 }
548 Ok(self)
549 }
550
551 #[cfg(feature = "rustls-0_23")]
558 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
559 mut self,
560 addrs: A,
561 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
562 ) -> io::Result<Self> {
563 let sockets = bind_addrs(addrs, self.backlog)?;
564 for lst in sockets {
565 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
566 }
567 Ok(self)
568 }
569
570 #[cfg(feature = "openssl")]
577 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
578 where
579 A: net::ToSocketAddrs,
580 {
581 let sockets = bind_addrs(addrs, self.backlog)?;
582 let acceptor = openssl_acceptor(builder)?;
583
584 for lst in sockets {
585 self = self.listen_openssl_inner(lst, acceptor.clone())?;
586 }
587
588 Ok(self)
589 }
590
591 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
596 let cfg = Arc::clone(&self.config);
597 let factory = self.factory.clone();
598 let addr = lst.local_addr().unwrap();
599
600 self.sockets.push(Socket {
601 addr,
602 scheme: "http",
603 });
604
605 let on_connect_fn = self.on_connect_fn.clone();
606
607 self.builder =
608 self.builder
609 .listen(format!("actix-web-service-{}", addr), lst, move || {
610 let cfg = cfg.lock().unwrap();
611 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
612
613 let mut svc = HttpService::build()
614 .keep_alive(cfg.keep_alive)
615 .client_request_timeout(cfg.client_request_timeout)
616 .client_disconnect_timeout(cfg.client_disconnect_timeout)
617 .h1_allow_half_closed(cfg.h1_allow_half_closed)
618 .local_addr(addr);
619
620 if let Some(enabled) = cfg.tcp_nodelay {
621 svc = svc.tcp_nodelay(enabled);
622 }
623
624 if let Some(val) = cfg.h2_initial_window_size {
625 svc = svc.h2_initial_window_size(val);
626 }
627
628 if let Some(val) = cfg.h2_initial_connection_window_size {
629 svc = svc.h2_initial_connection_window_size(val);
630 }
631
632 if let Some(handler) = on_connect_fn.clone() {
633 svc =
634 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
635 };
636
637 let fac = factory()
638 .into_factory()
639 .map_err(|err| err.into().error_response());
640
641 svc.finish(map_config(fac, move |_| {
642 AppConfig::new(false, host.clone(), addr)
643 }))
644 .tcp()
645 })?;
646
647 Ok(self)
648 }
649
650 #[cfg(feature = "http2")]
652 pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
653 let cfg = Arc::clone(&self.config);
654 let factory = self.factory.clone();
655 let addr = lst.local_addr().unwrap();
656
657 self.sockets.push(Socket {
658 addr,
659 scheme: "http",
660 });
661
662 let on_connect_fn = self.on_connect_fn.clone();
663
664 self.builder =
665 self.builder
666 .listen(format!("actix-web-service-{}", addr), lst, move || {
667 let cfg = cfg.lock().unwrap();
668 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
669
670 let mut svc = HttpService::build()
671 .keep_alive(cfg.keep_alive)
672 .client_request_timeout(cfg.client_request_timeout)
673 .client_disconnect_timeout(cfg.client_disconnect_timeout)
674 .h1_allow_half_closed(cfg.h1_allow_half_closed)
675 .local_addr(addr);
676
677 if let Some(enabled) = cfg.tcp_nodelay {
678 svc = svc.tcp_nodelay(enabled);
679 }
680
681 if let Some(val) = cfg.h2_initial_window_size {
682 svc = svc.h2_initial_window_size(val);
683 }
684
685 if let Some(val) = cfg.h2_initial_connection_window_size {
686 svc = svc.h2_initial_connection_window_size(val);
687 }
688
689 if let Some(handler) = on_connect_fn.clone() {
690 svc =
691 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
692 };
693
694 let fac = factory()
695 .into_factory()
696 .map_err(|err| err.into().error_response());
697
698 svc.finish(map_config(fac, move |_| {
699 AppConfig::new(false, host.clone(), addr)
700 }))
701 .tcp_auto_h2c()
702 })?;
703
704 Ok(self)
705 }
706
707 #[cfg(feature = "rustls-0_20")]
714 pub fn listen_rustls(
715 self,
716 lst: net::TcpListener,
717 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
718 ) -> io::Result<Self> {
719 self.listen_rustls_0_20_inner(lst, config)
720 }
721
722 #[cfg(feature = "rustls-0_21")]
729 pub fn listen_rustls_0_21(
730 self,
731 lst: net::TcpListener,
732 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
733 ) -> io::Result<Self> {
734 self.listen_rustls_0_21_inner(lst, config)
735 }
736
737 #[cfg(feature = "rustls-0_20")]
738 fn listen_rustls_0_20_inner(
739 mut self,
740 lst: net::TcpListener,
741 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
742 ) -> io::Result<Self> {
743 let factory = self.factory.clone();
744 let cfg = Arc::clone(&self.config);
745 let addr = lst.local_addr().unwrap();
746 self.sockets.push(Socket {
747 addr,
748 scheme: "https",
749 });
750
751 let on_connect_fn = self.on_connect_fn.clone();
752
753 self.builder =
754 self.builder
755 .listen(format!("actix-web-service-{}", addr), lst, move || {
756 let c = cfg.lock().unwrap();
757 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
758
759 let mut svc = HttpService::build()
760 .keep_alive(c.keep_alive)
761 .client_request_timeout(c.client_request_timeout)
762 .h1_allow_half_closed(c.h1_allow_half_closed)
763 .client_disconnect_timeout(c.client_disconnect_timeout);
764
765 if let Some(enabled) = c.tcp_nodelay {
766 svc = svc.tcp_nodelay(enabled);
767 }
768
769 if let Some(val) = c.h2_initial_window_size {
770 svc = svc.h2_initial_window_size(val);
771 }
772
773 if let Some(val) = c.h2_initial_connection_window_size {
774 svc = svc.h2_initial_connection_window_size(val);
775 }
776
777 if let Some(handler) = on_connect_fn.clone() {
778 svc = svc
779 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
780 };
781
782 let fac = factory()
783 .into_factory()
784 .map_err(|err| err.into().error_response());
785
786 let acceptor_config = match c.tls_handshake_timeout {
787 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
788 None => TlsAcceptorConfig::default(),
789 };
790
791 svc.finish(map_config(fac, move |_| {
792 AppConfig::new(true, host.clone(), addr)
793 }))
794 .rustls_with_config(config.clone(), acceptor_config)
795 })?;
796
797 Ok(self)
798 }
799
800 #[cfg(feature = "rustls-0_21")]
801 fn listen_rustls_0_21_inner(
802 mut self,
803 lst: net::TcpListener,
804 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
805 ) -> io::Result<Self> {
806 let factory = self.factory.clone();
807 let cfg = Arc::clone(&self.config);
808 let addr = lst.local_addr().unwrap();
809 self.sockets.push(Socket {
810 addr,
811 scheme: "https",
812 });
813
814 let on_connect_fn = self.on_connect_fn.clone();
815
816 self.builder =
817 self.builder
818 .listen(format!("actix-web-service-{}", addr), lst, move || {
819 let c = cfg.lock().unwrap();
820 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
821
822 let mut svc = HttpService::build()
823 .keep_alive(c.keep_alive)
824 .client_request_timeout(c.client_request_timeout)
825 .h1_allow_half_closed(c.h1_allow_half_closed)
826 .client_disconnect_timeout(c.client_disconnect_timeout);
827
828 if let Some(enabled) = c.tcp_nodelay {
829 svc = svc.tcp_nodelay(enabled);
830 }
831
832 if let Some(val) = c.h2_initial_window_size {
833 svc = svc.h2_initial_window_size(val);
834 }
835
836 if let Some(val) = c.h2_initial_connection_window_size {
837 svc = svc.h2_initial_connection_window_size(val);
838 }
839
840 if let Some(handler) = on_connect_fn.clone() {
841 svc = svc
842 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
843 };
844
845 let fac = factory()
846 .into_factory()
847 .map_err(|err| err.into().error_response());
848
849 let acceptor_config = match c.tls_handshake_timeout {
850 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
851 None => TlsAcceptorConfig::default(),
852 };
853
854 svc.finish(map_config(fac, move |_| {
855 AppConfig::new(true, host.clone(), addr)
856 }))
857 .rustls_021_with_config(config.clone(), acceptor_config)
858 })?;
859
860 Ok(self)
861 }
862
863 #[cfg(feature = "rustls-0_22")]
870 pub fn listen_rustls_0_22(
871 self,
872 lst: net::TcpListener,
873 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
874 ) -> io::Result<Self> {
875 self.listen_rustls_0_22_inner(lst, config)
876 }
877
878 #[cfg(feature = "rustls-0_22")]
879 fn listen_rustls_0_22_inner(
880 mut self,
881 lst: net::TcpListener,
882 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
883 ) -> io::Result<Self> {
884 let factory = self.factory.clone();
885 let cfg = Arc::clone(&self.config);
886 let addr = lst.local_addr().unwrap();
887 self.sockets.push(Socket {
888 addr,
889 scheme: "https",
890 });
891
892 let on_connect_fn = self.on_connect_fn.clone();
893
894 self.builder =
895 self.builder
896 .listen(format!("actix-web-service-{}", addr), lst, move || {
897 let c = cfg.lock().unwrap();
898 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
899
900 let mut svc = HttpService::build()
901 .keep_alive(c.keep_alive)
902 .client_request_timeout(c.client_request_timeout)
903 .h1_allow_half_closed(c.h1_allow_half_closed)
904 .client_disconnect_timeout(c.client_disconnect_timeout);
905
906 if let Some(enabled) = c.tcp_nodelay {
907 svc = svc.tcp_nodelay(enabled);
908 }
909
910 if let Some(val) = c.h2_initial_window_size {
911 svc = svc.h2_initial_window_size(val);
912 }
913
914 if let Some(val) = c.h2_initial_connection_window_size {
915 svc = svc.h2_initial_connection_window_size(val);
916 }
917
918 if let Some(handler) = on_connect_fn.clone() {
919 svc = svc
920 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
921 };
922
923 let fac = factory()
924 .into_factory()
925 .map_err(|err| err.into().error_response());
926
927 let acceptor_config = match c.tls_handshake_timeout {
928 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
929 None => TlsAcceptorConfig::default(),
930 };
931
932 svc.finish(map_config(fac, move |_| {
933 AppConfig::new(true, host.clone(), addr)
934 }))
935 .rustls_0_22_with_config(config.clone(), acceptor_config)
936 })?;
937
938 Ok(self)
939 }
940
941 #[cfg(feature = "rustls-0_23")]
948 pub fn listen_rustls_0_23(
949 self,
950 lst: net::TcpListener,
951 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
952 ) -> io::Result<Self> {
953 self.listen_rustls_0_23_inner(lst, config)
954 }
955
956 #[cfg(feature = "rustls-0_23")]
957 fn listen_rustls_0_23_inner(
958 mut self,
959 lst: net::TcpListener,
960 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
961 ) -> io::Result<Self> {
962 let factory = self.factory.clone();
963 let cfg = Arc::clone(&self.config);
964 let addr = lst.local_addr().unwrap();
965 self.sockets.push(Socket {
966 addr,
967 scheme: "https",
968 });
969
970 let on_connect_fn = self.on_connect_fn.clone();
971
972 self.builder =
973 self.builder
974 .listen(format!("actix-web-service-{}", addr), lst, move || {
975 let c = cfg.lock().unwrap();
976 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
977
978 let mut svc = HttpService::build()
979 .keep_alive(c.keep_alive)
980 .client_request_timeout(c.client_request_timeout)
981 .h1_allow_half_closed(c.h1_allow_half_closed)
982 .client_disconnect_timeout(c.client_disconnect_timeout);
983
984 if let Some(enabled) = c.tcp_nodelay {
985 svc = svc.tcp_nodelay(enabled);
986 }
987
988 if let Some(val) = c.h2_initial_window_size {
989 svc = svc.h2_initial_window_size(val);
990 }
991
992 if let Some(val) = c.h2_initial_connection_window_size {
993 svc = svc.h2_initial_connection_window_size(val);
994 }
995
996 if let Some(handler) = on_connect_fn.clone() {
997 svc = svc
998 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
999 };
1000
1001 let fac = factory()
1002 .into_factory()
1003 .map_err(|err| err.into().error_response());
1004
1005 let acceptor_config = match c.tls_handshake_timeout {
1006 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1007 None => TlsAcceptorConfig::default(),
1008 };
1009
1010 svc.finish(map_config(fac, move |_| {
1011 AppConfig::new(true, host.clone(), addr)
1012 }))
1013 .rustls_0_23_with_config(config.clone(), acceptor_config)
1014 })?;
1015
1016 Ok(self)
1017 }
1018
1019 #[cfg(feature = "openssl")]
1025 pub fn listen_openssl(
1026 self,
1027 lst: net::TcpListener,
1028 builder: SslAcceptorBuilder,
1029 ) -> io::Result<Self> {
1030 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1031 }
1032
1033 #[cfg(feature = "openssl")]
1034 fn listen_openssl_inner(
1035 mut self,
1036 lst: net::TcpListener,
1037 acceptor: SslAcceptor,
1038 ) -> io::Result<Self> {
1039 let factory = self.factory.clone();
1040 let cfg = Arc::clone(&self.config);
1041 let addr = lst.local_addr().unwrap();
1042
1043 self.sockets.push(Socket {
1044 addr,
1045 scheme: "https",
1046 });
1047
1048 let on_connect_fn = self.on_connect_fn.clone();
1049
1050 self.builder =
1051 self.builder
1052 .listen(format!("actix-web-service-{}", addr), lst, move || {
1053 let c = cfg.lock().unwrap();
1054 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1055
1056 let mut svc = HttpService::build()
1057 .keep_alive(c.keep_alive)
1058 .client_request_timeout(c.client_request_timeout)
1059 .client_disconnect_timeout(c.client_disconnect_timeout)
1060 .h1_allow_half_closed(c.h1_allow_half_closed)
1061 .local_addr(addr);
1062
1063 if let Some(enabled) = c.tcp_nodelay {
1064 svc = svc.tcp_nodelay(enabled);
1065 }
1066
1067 if let Some(val) = c.h2_initial_window_size {
1068 svc = svc.h2_initial_window_size(val);
1069 }
1070
1071 if let Some(val) = c.h2_initial_connection_window_size {
1072 svc = svc.h2_initial_connection_window_size(val);
1073 }
1074
1075 if let Some(handler) = on_connect_fn.clone() {
1076 svc = svc
1077 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1078 };
1079
1080 let fac = factory()
1081 .into_factory()
1082 .map_err(|err| err.into().error_response());
1083
1084 #[allow(clippy::significant_drop_in_scrutinee)]
1086 let acceptor_config = match c.tls_handshake_timeout {
1087 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1088 None => TlsAcceptorConfig::default(),
1089 };
1090
1091 svc.finish(map_config(fac, move |_| {
1092 AppConfig::new(true, host.clone(), addr)
1093 }))
1094 .openssl_with_config(acceptor.clone(), acceptor_config)
1095 })?;
1096
1097 Ok(self)
1098 }
1099
1100 #[cfg(unix)]
1102 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1103 where
1104 A: AsRef<std::path::Path>,
1105 {
1106 use actix_http::Protocol;
1107 use actix_rt::net::UnixStream;
1108 use actix_service::{fn_service, ServiceFactoryExt as _};
1109
1110 let cfg = Arc::clone(&self.config);
1111 let factory = self.factory.clone();
1112 let socket_addr =
1113 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1114
1115 self.sockets.push(Socket {
1116 scheme: "http",
1117 addr: socket_addr,
1118 });
1119
1120 self.builder = self.builder.bind_uds(
1121 format!("actix-web-service-{:?}", uds_path.as_ref()),
1122 uds_path,
1123 move || {
1124 let c = cfg.lock().unwrap();
1125 let config = AppConfig::new(
1126 false,
1127 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1128 socket_addr,
1129 );
1130
1131 let fac = factory()
1132 .into_factory()
1133 .map_err(|err| err.into().error_response());
1134
1135 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then(
1136 HttpService::build()
1137 .keep_alive(c.keep_alive)
1138 .client_request_timeout(c.client_request_timeout)
1139 .client_disconnect_timeout(c.client_disconnect_timeout)
1140 .h1_allow_half_closed(c.h1_allow_half_closed)
1141 .finish(map_config(fac, move |_| config.clone())),
1142 )
1143 },
1144 )?;
1145
1146 Ok(self)
1147 }
1148
1149 #[cfg(unix)]
1151 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1152 use actix_http::Protocol;
1153 use actix_rt::net::UnixStream;
1154 use actix_service::{fn_service, ServiceFactoryExt as _};
1155
1156 let cfg = Arc::clone(&self.config);
1157 let factory = self.factory.clone();
1158 let socket_addr =
1159 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1160
1161 self.sockets.push(Socket {
1162 scheme: "http",
1163 addr: socket_addr,
1164 });
1165
1166 let addr = lst.local_addr()?;
1167 let name = format!("actix-web-service-{:?}", addr);
1168 let on_connect_fn = self.on_connect_fn.clone();
1169
1170 self.builder = self.builder.listen_uds(name, lst, move || {
1171 let c = cfg.lock().unwrap();
1172 let config = AppConfig::new(
1173 false,
1174 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1175 socket_addr,
1176 );
1177
1178 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1179 let mut svc = HttpService::build()
1180 .keep_alive(c.keep_alive)
1181 .client_request_timeout(c.client_request_timeout)
1182 .h1_allow_half_closed(c.h1_allow_half_closed)
1183 .client_disconnect_timeout(c.client_disconnect_timeout);
1184
1185 if let Some(handler) = on_connect_fn.clone() {
1186 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1187 }
1188
1189 let fac = factory()
1190 .into_factory()
1191 .map_err(|err| err.into().error_response());
1192
1193 svc.finish(map_config(fac, move |_| config.clone()))
1194 })
1195 })?;
1196 Ok(self)
1197 }
1198}
1199
1200impl<F, I, S, B> HttpServer<F, I, S, B>
1201where
1202 F: Fn() -> I + Send + Clone + 'static,
1203 I: IntoServiceFactory<S, Request>,
1204 S: ServiceFactory<Request, Config = AppConfig>,
1205 S::Error: Into<Error>,
1206 S::InitError: fmt::Debug,
1207 S::Response: Into<Response<B>>,
1208 S::Service: 'static,
1209 B: MessageBody,
1210{
1211 pub fn run(self) -> Server {
1224 self.builder.run()
1225 }
1226}
1227
1228fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1230 let mut err = None;
1231 let mut success = false;
1232 let mut sockets = Vec::new();
1233
1234 for addr in addrs.to_socket_addrs()? {
1235 match create_tcp_listener(addr, backlog) {
1236 Ok(lst) => {
1237 success = true;
1238 sockets.push(lst);
1239 }
1240 Err(error) => err = Some(error),
1241 }
1242 }
1243
1244 if success {
1245 Ok(sockets)
1246 } else if let Some(err) = err.take() {
1247 Err(err)
1248 } else {
1249 Err(io::Error::other("Could not bind to address"))
1250 }
1251}
1252
1253fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1255 use socket2::{Domain, Protocol, Socket, Type};
1256 let domain = Domain::for_address(addr);
1257 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1258 #[cfg(not(windows))]
1259 {
1260 socket.set_reuse_address(true)?;
1261 }
1262 socket.bind(&addr.into())?;
1263 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1265 socket.listen(backlog)?;
1266 Ok(net::TcpListener::from(socket))
1267}
1268
1269#[cfg(feature = "openssl")]
1271fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1272 builder.set_alpn_select_callback(|_, protocols| {
1273 const H2: &[u8] = b"\x02h2";
1274 const H11: &[u8] = b"\x08http/1.1";
1275
1276 if protocols.windows(3).any(|window| window == H2) {
1277 Ok(b"h2")
1278 } else if protocols.windows(9).any(|window| window == H11) {
1279 Ok(b"http/1.1")
1280 } else {
1281 Err(AlpnError::NOACK)
1282 }
1283 });
1284
1285 builder.set_alpn_protos(b"\x08http/1.1\x02h2")?;
1286
1287 Ok(builder.build())
1288}