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::{GracefulShutdownSignal, 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 h1_write_buffer_size: Option<usize>,
37 h2_initial_window_size: Option<u32>,
38 h2_initial_connection_window_size: Option<u32>,
39 #[allow(dead_code)] tls_handshake_timeout: Option<Duration>,
41}
42
43#[must_use]
76pub struct HttpServer<F, I, S, B>
77where
78 F: Fn() -> I + Send + Clone + 'static,
79 I: IntoServiceFactory<S, Request>,
80 S: ServiceFactory<Request, Config = AppConfig>,
81 S::Error: Into<Error>,
82 S::InitError: fmt::Debug,
83 S::Response: Into<Response<B>>,
84 B: MessageBody,
85{
86 pub(super) factory: F,
87 config: Arc<Mutex<Config>>,
88 backlog: u32,
89 #[cfg(feature = "http2")]
90 auto_h2c: bool,
91 sockets: Vec<Socket>,
92 builder: ServerBuilder,
93 graceful_shutdown_signal: GracefulShutdownSignal,
94 #[allow(clippy::type_complexity)]
95 on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
96 _phantom: PhantomData<(S, B)>,
97}
98
99impl<F, I, S, B> HttpServer<F, I, S, B>
100where
101 F: Fn() -> I + Send + Clone + 'static,
102 I: IntoServiceFactory<S, Request>,
103
104 S: ServiceFactory<Request, Config = AppConfig> + 'static,
105 S::Error: Into<Error> + 'static,
106 S::InitError: fmt::Debug,
107 S::Response: Into<Response<B>> + 'static,
108 <S::Service as Service<Request>>::Future: 'static,
109 S::Service: 'static,
110
111 B: MessageBody + 'static,
112{
113 pub fn new(factory: F) -> Self {
121 let builder = ServerBuilder::default();
122 let graceful_shutdown_signal = builder.graceful_shutdown_signal();
123
124 HttpServer {
125 factory,
126 config: Arc::new(Mutex::new(Config {
127 host: None,
128 keep_alive: KeepAlive::default(),
129 tcp_nodelay: Some(true),
130 client_request_timeout: Duration::from_secs(5),
131 client_disconnect_timeout: Duration::from_secs(1),
132 h1_allow_half_closed: true,
133 h1_write_buffer_size: None,
134 h2_initial_window_size: None,
135 h2_initial_connection_window_size: None,
136 tls_handshake_timeout: None,
137 })),
138 backlog: 1024,
139 #[cfg(feature = "http2")]
140 auto_h2c: true,
141 sockets: Vec::new(),
142 builder,
143 graceful_shutdown_signal,
144 on_connect_fn: None,
145 _phantom: PhantomData,
146 }
147 }
148
149 pub fn workers(mut self, num: usize) -> Self {
164 self.builder = self.builder.workers(num);
165 self
166 }
167
168 pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
172 self.config.lock().unwrap().keep_alive = val.into();
173 self
174 }
175
176 pub fn tcp_nodelay(self, enabled: bool) -> Self {
180 self.config.lock().unwrap().tcp_nodelay = Some(enabled);
181 self
182 }
183
184 pub fn backlog(mut self, backlog: u32) -> Self {
194 self.backlog = backlog;
195 self.builder = self.builder.backlog(backlog);
196 self
197 }
198
199 pub fn max_connections(mut self, num: usize) -> Self {
206 self.builder = self.builder.max_concurrent_connections(num);
207 self
208 }
209
210 #[allow(unused_variables)]
217 pub fn max_connection_rate(self, num: usize) -> Self {
218 #[cfg(feature = "__tls")]
219 actix_tls::accept::max_concurrent_tls_connect(num);
220 self
221 }
222
223 pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
229 self.builder = self.builder.worker_max_blocking_threads(num);
230 self
231 }
232
233 pub fn client_request_timeout(self, dur: Duration) -> Self {
242 self.config.lock().unwrap().client_request_timeout = dur;
243 self
244 }
245
246 #[doc(hidden)]
247 #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
248 pub fn client_timeout(self, dur: Duration) -> Self {
249 self.client_request_timeout(dur)
250 }
251
252 pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
261 self.config.lock().unwrap().client_disconnect_timeout = dur;
262 self
263 }
264
265 #[cfg(feature = "__tls")]
272 pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
273 self.config
274 .lock()
275 .unwrap()
276 .tls_handshake_timeout
277 .replace(dur);
278
279 self
280 }
281
282 #[doc(hidden)]
283 #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
284 pub fn client_shutdown(self, dur: u64) -> Self {
285 self.client_disconnect_timeout(Duration::from_millis(dur))
286 }
287
288 pub fn h1_allow_half_closed(self, allow: bool) -> Self {
296 self.config.lock().unwrap().h1_allow_half_closed = allow;
297 self
298 }
299
300 pub fn h1_write_buffer_size(self, size: usize) -> Self {
310 assert!(
311 size > 0,
312 "HTTP/1 write buffer size must be greater than zero"
313 );
314
315 self.config.lock().unwrap().h1_write_buffer_size = Some(size);
316 self
317 }
318
319 #[cfg(feature = "http2")]
326 pub fn h2_initial_window_size(self, size: u32) -> Self {
327 self.config.lock().unwrap().h2_initial_window_size = Some(size);
328 self
329 }
330
331 #[cfg(feature = "http2")]
338 pub fn h2_initial_connection_window_size(self, size: u32) -> Self {
339 self.config
340 .lock()
341 .unwrap()
342 .h2_initial_connection_window_size = Some(size);
343 self
344 }
345
346 pub fn on_connect<CB>(mut self, f: CB) -> HttpServer<F, I, S, B>
370 where
371 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
372 {
373 self.on_connect_fn = Some(Arc::new(f));
374 self
375 }
376
377 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
384 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
385 self
386 }
387
388 pub fn system_exit(mut self) -> Self {
392 self.builder = self.builder.system_exit();
393 self
394 }
395
396 pub fn disable_signals(mut self) -> Self {
398 self.builder = self.builder.disable_signals();
399 self
400 }
401
402 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
426 where
427 Fut: Future<Output = ()> + Send + 'static,
428 {
429 self.builder = self.builder.shutdown_signal(shutdown_signal);
430 self
431 }
432
433 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
440 self.builder = self.builder.shutdown_timeout(sec);
441 self
442 }
443
444 pub fn addrs(&self) -> Vec<net::SocketAddr> {
446 self.sockets.iter().map(|s| s.addr).collect()
447 }
448
449 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
455 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
456 }
457
458 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
516 let sockets = bind_addrs(addrs, self.backlog)?;
517
518 for lst in sockets {
519 self = self.listen(lst)?;
520 }
521
522 Ok(self)
523 }
524
525 #[cfg(feature = "http2")]
534 pub fn auto_h2c(mut self, enabled: bool) -> Self {
535 self.auto_h2c = enabled;
536 self
537 }
538
539 #[cfg(feature = "http2")]
544 #[deprecated(
545 since = "4.19.0",
546 note = "Automatic h2c detection is now enabled by default. Use `bind()` instead."
547 )]
548 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
549 let sockets = bind_addrs(addrs, self.backlog)?;
550
551 for lst in sockets {
552 self = self.listen_auto_h2c_inner(lst)?;
553 }
554
555 Ok(self)
556 }
557
558 #[cfg(feature = "rustls-0_20")]
566 pub fn bind_rustls<A: net::ToSocketAddrs>(
567 mut self,
568 addrs: A,
569 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
570 ) -> io::Result<Self> {
571 let sockets = bind_addrs(addrs, self.backlog)?;
572 for lst in sockets {
573 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
574 }
575 Ok(self)
576 }
577
578 #[cfg(feature = "rustls-0_21")]
586 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
587 mut self,
588 addrs: A,
589 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
590 ) -> io::Result<Self> {
591 let sockets = bind_addrs(addrs, self.backlog)?;
592 for lst in sockets {
593 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
594 }
595 Ok(self)
596 }
597
598 #[cfg(feature = "rustls-0_22")]
606 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
607 mut self,
608 addrs: A,
609 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
610 ) -> io::Result<Self> {
611 let sockets = bind_addrs(addrs, self.backlog)?;
612 for lst in sockets {
613 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
614 }
615 Ok(self)
616 }
617
618 #[cfg(feature = "rustls-0_23")]
626 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
627 mut self,
628 addrs: A,
629 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
630 ) -> io::Result<Self> {
631 let sockets = bind_addrs(addrs, self.backlog)?;
632 for lst in sockets {
633 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
634 }
635 Ok(self)
636 }
637
638 #[cfg(feature = "openssl")]
646 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
647 where
648 A: net::ToSocketAddrs,
649 {
650 let sockets = bind_addrs(addrs, self.backlog)?;
651 let acceptor = openssl_acceptor(builder)?;
652
653 for lst in sockets {
654 self = self.listen_openssl_inner(lst, acceptor.clone())?;
655 }
656
657 Ok(self)
658 }
659
660 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
668 #[cfg(feature = "http2")]
669 if self.auto_h2c {
670 return self.listen_auto_h2c_inner(lst);
671 }
672
673 let cfg = Arc::clone(&self.config);
674 let factory = self.factory.clone();
675 let addr = lst.local_addr().unwrap();
676
677 self.sockets.push(Socket {
678 addr,
679 scheme: "http",
680 });
681
682 let on_connect_fn = self.on_connect_fn.clone();
683 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
684
685 self.builder =
686 self.builder
687 .listen(format!("actix-web-service-{}", addr), lst, move || {
688 let cfg = cfg.lock().unwrap();
689 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
690 let shutdown_signal = graceful_shutdown_signal.clone();
691
692 let mut svc = HttpService::build()
693 .graceful_shutdown_signal(move || {
694 let signal = shutdown_signal.clone();
695 async move { signal.notified().await }
696 })
697 .keep_alive(cfg.keep_alive)
698 .client_request_timeout(cfg.client_request_timeout)
699 .client_disconnect_timeout(cfg.client_disconnect_timeout)
700 .h1_allow_half_closed(cfg.h1_allow_half_closed)
701 .local_addr(addr);
702
703 if let Some(enabled) = cfg.tcp_nodelay {
704 svc = svc.tcp_nodelay(enabled);
705 }
706
707 if let Some(size) = cfg.h1_write_buffer_size {
708 svc = svc.h1_write_buffer_size(size);
709 }
710
711 if let Some(val) = cfg.h2_initial_window_size {
712 svc = svc.h2_initial_window_size(val);
713 }
714
715 if let Some(val) = cfg.h2_initial_connection_window_size {
716 svc = svc.h2_initial_connection_window_size(val);
717 }
718
719 if let Some(handler) = on_connect_fn.clone() {
720 svc =
721 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
722 };
723
724 let fac = factory()
725 .into_factory()
726 .map_err(|err| err.into().error_response());
727
728 svc.finish(map_config(fac, move |_| {
729 AppConfig::new(false, host.clone(), addr)
730 }))
731 .tcp()
732 })?;
733
734 Ok(self)
735 }
736
737 #[cfg(feature = "http2")]
739 #[deprecated(
740 since = "4.19.0",
741 note = "Automatic h2c detection is now enabled by default. Use `listen()` instead."
742 )]
743 pub fn listen_auto_h2c(self, lst: net::TcpListener) -> io::Result<Self> {
744 self.listen_auto_h2c_inner(lst)
745 }
746
747 #[cfg(feature = "http2")]
748 fn listen_auto_h2c_inner(mut self, lst: net::TcpListener) -> io::Result<Self> {
749 let cfg = Arc::clone(&self.config);
750 let factory = self.factory.clone();
751 let addr = lst.local_addr().unwrap();
752
753 self.sockets.push(Socket {
754 addr,
755 scheme: "http",
756 });
757
758 let on_connect_fn = self.on_connect_fn.clone();
759 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
760
761 self.builder =
762 self.builder
763 .listen(format!("actix-web-service-{}", addr), lst, move || {
764 let cfg = cfg.lock().unwrap();
765 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
766 let shutdown_signal = graceful_shutdown_signal.clone();
767
768 let mut svc = HttpService::build()
769 .graceful_shutdown_signal(move || {
770 let signal = shutdown_signal.clone();
771 async move { signal.notified().await }
772 })
773 .keep_alive(cfg.keep_alive)
774 .client_request_timeout(cfg.client_request_timeout)
775 .client_disconnect_timeout(cfg.client_disconnect_timeout)
776 .h1_allow_half_closed(cfg.h1_allow_half_closed)
777 .local_addr(addr);
778
779 if let Some(enabled) = cfg.tcp_nodelay {
780 svc = svc.tcp_nodelay(enabled);
781 }
782
783 if let Some(size) = cfg.h1_write_buffer_size {
784 svc = svc.h1_write_buffer_size(size);
785 }
786
787 if let Some(val) = cfg.h2_initial_window_size {
788 svc = svc.h2_initial_window_size(val);
789 }
790
791 if let Some(val) = cfg.h2_initial_connection_window_size {
792 svc = svc.h2_initial_connection_window_size(val);
793 }
794
795 if let Some(handler) = on_connect_fn.clone() {
796 svc =
797 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
798 };
799
800 let fac = factory()
801 .into_factory()
802 .map_err(|err| err.into().error_response());
803
804 svc.finish(map_config(fac, move |_| {
805 AppConfig::new(false, host.clone(), addr)
806 }))
807 .tcp_auto_h2c()
808 })?;
809
810 Ok(self)
811 }
812
813 #[cfg(feature = "rustls-0_20")]
821 pub fn listen_rustls(
822 self,
823 lst: net::TcpListener,
824 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
825 ) -> io::Result<Self> {
826 self.listen_rustls_0_20_inner(lst, config)
827 }
828
829 #[cfg(feature = "rustls-0_21")]
837 pub fn listen_rustls_0_21(
838 self,
839 lst: net::TcpListener,
840 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
841 ) -> io::Result<Self> {
842 self.listen_rustls_0_21_inner(lst, config)
843 }
844
845 #[cfg(feature = "rustls-0_20")]
846 fn listen_rustls_0_20_inner(
847 mut self,
848 lst: net::TcpListener,
849 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
850 ) -> io::Result<Self> {
851 let factory = self.factory.clone();
852 let cfg = Arc::clone(&self.config);
853 let addr = lst.local_addr().unwrap();
854 self.sockets.push(Socket {
855 addr,
856 scheme: "https",
857 });
858
859 let on_connect_fn = self.on_connect_fn.clone();
860 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
861
862 self.builder =
863 self.builder
864 .listen(format!("actix-web-service-{}", addr), lst, move || {
865 let c = cfg.lock().unwrap();
866 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
867 let shutdown_signal = graceful_shutdown_signal.clone();
868
869 let mut svc = HttpService::build()
870 .graceful_shutdown_signal(move || {
871 let signal = shutdown_signal.clone();
872 async move { signal.notified().await }
873 })
874 .keep_alive(c.keep_alive)
875 .client_request_timeout(c.client_request_timeout)
876 .h1_allow_half_closed(c.h1_allow_half_closed)
877 .client_disconnect_timeout(c.client_disconnect_timeout);
878
879 if let Some(enabled) = c.tcp_nodelay {
880 svc = svc.tcp_nodelay(enabled);
881 }
882
883 if let Some(size) = c.h1_write_buffer_size {
884 svc = svc.h1_write_buffer_size(size);
885 }
886
887 if let Some(val) = c.h2_initial_window_size {
888 svc = svc.h2_initial_window_size(val);
889 }
890
891 if let Some(val) = c.h2_initial_connection_window_size {
892 svc = svc.h2_initial_connection_window_size(val);
893 }
894
895 if let Some(handler) = on_connect_fn.clone() {
896 svc = svc
897 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
898 };
899
900 let fac = factory()
901 .into_factory()
902 .map_err(|err| err.into().error_response());
903
904 let acceptor_config = match c.tls_handshake_timeout {
905 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
906 None => TlsAcceptorConfig::default(),
907 };
908
909 svc.finish(map_config(fac, move |_| {
910 AppConfig::new(true, host.clone(), addr)
911 }))
912 .rustls_with_config(config.clone(), acceptor_config)
913 })?;
914
915 Ok(self)
916 }
917
918 #[cfg(feature = "rustls-0_21")]
919 fn listen_rustls_0_21_inner(
920 mut self,
921 lst: net::TcpListener,
922 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
923 ) -> io::Result<Self> {
924 let factory = self.factory.clone();
925 let cfg = Arc::clone(&self.config);
926 let addr = lst.local_addr().unwrap();
927 self.sockets.push(Socket {
928 addr,
929 scheme: "https",
930 });
931
932 let on_connect_fn = self.on_connect_fn.clone();
933 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
934
935 self.builder =
936 self.builder
937 .listen(format!("actix-web-service-{}", addr), lst, move || {
938 let c = cfg.lock().unwrap();
939 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
940 let shutdown_signal = graceful_shutdown_signal.clone();
941
942 let mut svc = HttpService::build()
943 .graceful_shutdown_signal(move || {
944 let signal = shutdown_signal.clone();
945 async move { signal.notified().await }
946 })
947 .keep_alive(c.keep_alive)
948 .client_request_timeout(c.client_request_timeout)
949 .h1_allow_half_closed(c.h1_allow_half_closed)
950 .client_disconnect_timeout(c.client_disconnect_timeout);
951
952 if let Some(enabled) = c.tcp_nodelay {
953 svc = svc.tcp_nodelay(enabled);
954 }
955
956 if let Some(size) = c.h1_write_buffer_size {
957 svc = svc.h1_write_buffer_size(size);
958 }
959
960 if let Some(val) = c.h2_initial_window_size {
961 svc = svc.h2_initial_window_size(val);
962 }
963
964 if let Some(val) = c.h2_initial_connection_window_size {
965 svc = svc.h2_initial_connection_window_size(val);
966 }
967
968 if let Some(handler) = on_connect_fn.clone() {
969 svc = svc
970 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
971 };
972
973 let fac = factory()
974 .into_factory()
975 .map_err(|err| err.into().error_response());
976
977 let acceptor_config = match c.tls_handshake_timeout {
978 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
979 None => TlsAcceptorConfig::default(),
980 };
981
982 svc.finish(map_config(fac, move |_| {
983 AppConfig::new(true, host.clone(), addr)
984 }))
985 .rustls_021_with_config(config.clone(), acceptor_config)
986 })?;
987
988 Ok(self)
989 }
990
991 #[cfg(feature = "rustls-0_22")]
999 pub fn listen_rustls_0_22(
1000 self,
1001 lst: net::TcpListener,
1002 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
1003 ) -> io::Result<Self> {
1004 self.listen_rustls_0_22_inner(lst, config)
1005 }
1006
1007 #[cfg(feature = "rustls-0_22")]
1008 fn listen_rustls_0_22_inner(
1009 mut self,
1010 lst: net::TcpListener,
1011 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
1012 ) -> io::Result<Self> {
1013 let factory = self.factory.clone();
1014 let cfg = Arc::clone(&self.config);
1015 let addr = lst.local_addr().unwrap();
1016 self.sockets.push(Socket {
1017 addr,
1018 scheme: "https",
1019 });
1020
1021 let on_connect_fn = self.on_connect_fn.clone();
1022 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1023
1024 self.builder =
1025 self.builder
1026 .listen(format!("actix-web-service-{}", addr), lst, move || {
1027 let c = cfg.lock().unwrap();
1028 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1029 let shutdown_signal = graceful_shutdown_signal.clone();
1030
1031 let mut svc = HttpService::build()
1032 .graceful_shutdown_signal(move || {
1033 let signal = shutdown_signal.clone();
1034 async move { signal.notified().await }
1035 })
1036 .keep_alive(c.keep_alive)
1037 .client_request_timeout(c.client_request_timeout)
1038 .h1_allow_half_closed(c.h1_allow_half_closed)
1039 .client_disconnect_timeout(c.client_disconnect_timeout);
1040
1041 if let Some(enabled) = c.tcp_nodelay {
1042 svc = svc.tcp_nodelay(enabled);
1043 }
1044
1045 if let Some(size) = c.h1_write_buffer_size {
1046 svc = svc.h1_write_buffer_size(size);
1047 }
1048
1049 if let Some(val) = c.h2_initial_window_size {
1050 svc = svc.h2_initial_window_size(val);
1051 }
1052
1053 if let Some(val) = c.h2_initial_connection_window_size {
1054 svc = svc.h2_initial_connection_window_size(val);
1055 }
1056
1057 if let Some(handler) = on_connect_fn.clone() {
1058 svc = svc
1059 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1060 };
1061
1062 let fac = factory()
1063 .into_factory()
1064 .map_err(|err| err.into().error_response());
1065
1066 let acceptor_config = match c.tls_handshake_timeout {
1067 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1068 None => TlsAcceptorConfig::default(),
1069 };
1070
1071 svc.finish(map_config(fac, move |_| {
1072 AppConfig::new(true, host.clone(), addr)
1073 }))
1074 .rustls_0_22_with_config(config.clone(), acceptor_config)
1075 })?;
1076
1077 Ok(self)
1078 }
1079
1080 #[cfg(feature = "rustls-0_23")]
1088 pub fn listen_rustls_0_23(
1089 self,
1090 lst: net::TcpListener,
1091 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1092 ) -> io::Result<Self> {
1093 self.listen_rustls_0_23_inner(lst, config)
1094 }
1095
1096 #[cfg(feature = "rustls-0_23")]
1097 fn listen_rustls_0_23_inner(
1098 mut self,
1099 lst: net::TcpListener,
1100 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1101 ) -> io::Result<Self> {
1102 let factory = self.factory.clone();
1103 let cfg = Arc::clone(&self.config);
1104 let addr = lst.local_addr().unwrap();
1105 self.sockets.push(Socket {
1106 addr,
1107 scheme: "https",
1108 });
1109
1110 let on_connect_fn = self.on_connect_fn.clone();
1111 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1112
1113 self.builder =
1114 self.builder
1115 .listen(format!("actix-web-service-{}", addr), lst, move || {
1116 let c = cfg.lock().unwrap();
1117 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1118 let shutdown_signal = graceful_shutdown_signal.clone();
1119
1120 let mut svc = HttpService::build()
1121 .graceful_shutdown_signal(move || {
1122 let signal = shutdown_signal.clone();
1123 async move { signal.notified().await }
1124 })
1125 .keep_alive(c.keep_alive)
1126 .client_request_timeout(c.client_request_timeout)
1127 .h1_allow_half_closed(c.h1_allow_half_closed)
1128 .client_disconnect_timeout(c.client_disconnect_timeout);
1129
1130 if let Some(enabled) = c.tcp_nodelay {
1131 svc = svc.tcp_nodelay(enabled);
1132 }
1133
1134 if let Some(size) = c.h1_write_buffer_size {
1135 svc = svc.h1_write_buffer_size(size);
1136 }
1137
1138 if let Some(val) = c.h2_initial_window_size {
1139 svc = svc.h2_initial_window_size(val);
1140 }
1141
1142 if let Some(val) = c.h2_initial_connection_window_size {
1143 svc = svc.h2_initial_connection_window_size(val);
1144 }
1145
1146 if let Some(handler) = on_connect_fn.clone() {
1147 svc = svc
1148 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1149 };
1150
1151 let fac = factory()
1152 .into_factory()
1153 .map_err(|err| err.into().error_response());
1154
1155 let acceptor_config = match c.tls_handshake_timeout {
1156 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1157 None => TlsAcceptorConfig::default(),
1158 };
1159
1160 svc.finish(map_config(fac, move |_| {
1161 AppConfig::new(true, host.clone(), addr)
1162 }))
1163 .rustls_0_23_with_config(config.clone(), acceptor_config)
1164 })?;
1165
1166 Ok(self)
1167 }
1168
1169 #[cfg(feature = "openssl")]
1176 pub fn listen_openssl(
1177 self,
1178 lst: net::TcpListener,
1179 builder: SslAcceptorBuilder,
1180 ) -> io::Result<Self> {
1181 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1182 }
1183
1184 #[cfg(feature = "openssl")]
1185 fn listen_openssl_inner(
1186 mut self,
1187 lst: net::TcpListener,
1188 acceptor: SslAcceptor,
1189 ) -> io::Result<Self> {
1190 let factory = self.factory.clone();
1191 let cfg = Arc::clone(&self.config);
1192 let addr = lst.local_addr().unwrap();
1193
1194 self.sockets.push(Socket {
1195 addr,
1196 scheme: "https",
1197 });
1198
1199 let on_connect_fn = self.on_connect_fn.clone();
1200 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1201
1202 self.builder =
1203 self.builder
1204 .listen(format!("actix-web-service-{}", addr), lst, move || {
1205 let c = cfg.lock().unwrap();
1206 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1207 let shutdown_signal = graceful_shutdown_signal.clone();
1208
1209 let mut svc = HttpService::build()
1210 .graceful_shutdown_signal(move || {
1211 let signal = shutdown_signal.clone();
1212 async move { signal.notified().await }
1213 })
1214 .keep_alive(c.keep_alive)
1215 .client_request_timeout(c.client_request_timeout)
1216 .client_disconnect_timeout(c.client_disconnect_timeout)
1217 .h1_allow_half_closed(c.h1_allow_half_closed)
1218 .local_addr(addr);
1219
1220 if let Some(enabled) = c.tcp_nodelay {
1221 svc = svc.tcp_nodelay(enabled);
1222 }
1223
1224 if let Some(size) = c.h1_write_buffer_size {
1225 svc = svc.h1_write_buffer_size(size);
1226 }
1227
1228 if let Some(val) = c.h2_initial_window_size {
1229 svc = svc.h2_initial_window_size(val);
1230 }
1231
1232 if let Some(val) = c.h2_initial_connection_window_size {
1233 svc = svc.h2_initial_connection_window_size(val);
1234 }
1235
1236 if let Some(handler) = on_connect_fn.clone() {
1237 svc = svc
1238 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1239 };
1240
1241 let fac = factory()
1242 .into_factory()
1243 .map_err(|err| err.into().error_response());
1244
1245 #[allow(clippy::significant_drop_in_scrutinee)]
1247 let acceptor_config = match c.tls_handshake_timeout {
1248 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1249 None => TlsAcceptorConfig::default(),
1250 };
1251
1252 svc.finish(map_config(fac, move |_| {
1253 AppConfig::new(true, host.clone(), addr)
1254 }))
1255 .openssl_with_config(acceptor.clone(), acceptor_config)
1256 })?;
1257
1258 Ok(self)
1259 }
1260
1261 #[cfg(unix)]
1263 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1264 where
1265 A: AsRef<std::path::Path>,
1266 {
1267 use actix_http::Protocol;
1268 use actix_service::{fn_service, ServiceFactoryExt as _};
1269 use tokio::net::UnixStream;
1270
1271 let cfg = Arc::clone(&self.config);
1272 let factory = self.factory.clone();
1273 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1274 let socket_addr =
1275 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1276
1277 self.sockets.push(Socket {
1278 scheme: "http",
1279 addr: socket_addr,
1280 });
1281
1282 self.builder = self.builder.bind_uds(
1283 format!("actix-web-service-{:?}", uds_path.as_ref()),
1284 uds_path,
1285 move || {
1286 let c = cfg.lock().unwrap();
1287 let config = AppConfig::new(
1288 false,
1289 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1290 socket_addr,
1291 );
1292
1293 let fac = factory()
1294 .into_factory()
1295 .map_err(|err| err.into().error_response());
1296
1297 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1298 let shutdown_signal = graceful_shutdown_signal.clone();
1299 let mut svc = HttpService::build()
1300 .graceful_shutdown_signal(move || {
1301 let signal = shutdown_signal.clone();
1302 async move { signal.notified().await }
1303 })
1304 .keep_alive(c.keep_alive)
1305 .client_request_timeout(c.client_request_timeout)
1306 .client_disconnect_timeout(c.client_disconnect_timeout)
1307 .h1_allow_half_closed(c.h1_allow_half_closed);
1308
1309 if let Some(size) = c.h1_write_buffer_size {
1310 svc = svc.h1_write_buffer_size(size);
1311 }
1312
1313 svc.finish(map_config(fac, move |_| config.clone()))
1314 })
1315 },
1316 )?;
1317
1318 Ok(self)
1319 }
1320
1321 #[cfg(unix)]
1323 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1324 use actix_http::Protocol;
1325 use actix_service::{fn_service, ServiceFactoryExt as _};
1326 use tokio::net::UnixStream;
1327
1328 let cfg = Arc::clone(&self.config);
1329 let factory = self.factory.clone();
1330 let socket_addr =
1331 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1332
1333 self.sockets.push(Socket {
1334 scheme: "http",
1335 addr: socket_addr,
1336 });
1337
1338 let addr = lst.local_addr()?;
1339 let name = format!("actix-web-service-{:?}", addr);
1340 let on_connect_fn = self.on_connect_fn.clone();
1341 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1342
1343 self.builder = self.builder.listen_uds(name, lst, move || {
1344 let c = cfg.lock().unwrap();
1345 let config = AppConfig::new(
1346 false,
1347 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1348 socket_addr,
1349 );
1350
1351 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1352 let shutdown_signal = graceful_shutdown_signal.clone();
1353 let mut svc = HttpService::build()
1354 .graceful_shutdown_signal(move || {
1355 let signal = shutdown_signal.clone();
1356 async move { signal.notified().await }
1357 })
1358 .keep_alive(c.keep_alive)
1359 .client_request_timeout(c.client_request_timeout)
1360 .h1_allow_half_closed(c.h1_allow_half_closed)
1361 .client_disconnect_timeout(c.client_disconnect_timeout);
1362
1363 if let Some(handler) = on_connect_fn.clone() {
1364 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1365 }
1366
1367 if let Some(size) = c.h1_write_buffer_size {
1368 svc = svc.h1_write_buffer_size(size);
1369 }
1370
1371 let fac = factory()
1372 .into_factory()
1373 .map_err(|err| err.into().error_response());
1374
1375 svc.finish(map_config(fac, move |_| config.clone()))
1376 })
1377 })?;
1378 Ok(self)
1379 }
1380}
1381
1382impl<F, I, S, B> HttpServer<F, I, S, B>
1383where
1384 F: Fn() -> I + Send + Clone + 'static,
1385 I: IntoServiceFactory<S, Request>,
1386 S: ServiceFactory<Request, Config = AppConfig>,
1387 S::Error: Into<Error>,
1388 S::InitError: fmt::Debug,
1389 S::Response: Into<Response<B>>,
1390 S::Service: 'static,
1391 B: MessageBody,
1392{
1393 pub fn run(self) -> Server {
1408 self.builder.run()
1409 }
1410}
1411
1412fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1414 let mut err = None;
1415 let mut success = false;
1416 let mut sockets = Vec::new();
1417
1418 for addr in addrs.to_socket_addrs()? {
1419 match create_tcp_listener(addr, backlog) {
1420 Ok(lst) => {
1421 success = true;
1422 sockets.push(lst);
1423 }
1424 Err(error) => err = Some(error),
1425 }
1426 }
1427
1428 if success {
1429 Ok(sockets)
1430 } else if let Some(err) = err.take() {
1431 Err(err)
1432 } else {
1433 Err(io::Error::other("Could not bind to address"))
1434 }
1435}
1436
1437fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1439 use socket2::{Domain, Protocol, Socket, Type};
1440 let domain = Domain::for_address(addr);
1441 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1442 #[cfg(not(windows))]
1443 {
1444 socket.set_reuse_address(true)?;
1445 }
1446 #[cfg(windows)]
1449 if addr.is_ipv6() {
1450 if let Err(err) = socket.set_only_v6(false) {
1451 log::warn!("failed to set IPV6_V6ONLY=false: {err}");
1452 }
1453 }
1454 socket.bind(&addr.into())?;
1455 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1457 socket.listen(backlog)?;
1458 Ok(net::TcpListener::from(socket))
1459}
1460
1461#[cfg(feature = "openssl")]
1463fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1464 builder.set_alpn_select_callback(|_, protocols| {
1465 const H11: &[u8] = b"\x08http/1.1";
1466
1467 #[cfg(feature = "http2")]
1468 {
1469 const H2: &[u8] = b"\x02h2";
1470
1471 if protocols.windows(3).any(|window| window == H2) {
1472 return Ok(b"h2");
1473 }
1474 }
1475
1476 if protocols.windows(9).any(|window| window == H11) {
1477 Ok(b"http/1.1")
1478 } else {
1479 Err(AlpnError::NOACK)
1480 }
1481 });
1482
1483 #[cfg(feature = "http2")]
1484 let protos = b"\x08http/1.1\x02h2";
1485 #[cfg(not(feature = "http2"))]
1486 let protos = b"\x08http/1.1";
1487 builder.set_alpn_protos(protos)?;
1488
1489 Ok(builder.build())
1490}