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]
75pub struct HttpServer<F, I, S, B>
76where
77 F: Fn() -> I + Send + Clone + 'static,
78 I: IntoServiceFactory<S, Request>,
79 S: ServiceFactory<Request, Config = AppConfig>,
80 S::Error: Into<Error>,
81 S::InitError: fmt::Debug,
82 S::Response: Into<Response<B>>,
83 B: MessageBody,
84{
85 pub(super) factory: F,
86 config: Arc<Mutex<Config>>,
87 backlog: u32,
88 sockets: Vec<Socket>,
89 builder: ServerBuilder,
90 graceful_shutdown_signal: GracefulShutdownSignal,
91 #[allow(clippy::type_complexity)]
92 on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
93 _phantom: PhantomData<(S, B)>,
94}
95
96impl<F, I, S, B> HttpServer<F, I, S, B>
97where
98 F: Fn() -> I + Send + Clone + 'static,
99 I: IntoServiceFactory<S, Request>,
100
101 S: ServiceFactory<Request, Config = AppConfig> + 'static,
102 S::Error: Into<Error> + 'static,
103 S::InitError: fmt::Debug,
104 S::Response: Into<Response<B>> + 'static,
105 <S::Service as Service<Request>>::Future: 'static,
106 S::Service: 'static,
107
108 B: MessageBody + 'static,
109{
110 pub fn new(factory: F) -> Self {
118 let builder = ServerBuilder::default();
119 let graceful_shutdown_signal = builder.graceful_shutdown_signal();
120
121 HttpServer {
122 factory,
123 config: Arc::new(Mutex::new(Config {
124 host: None,
125 keep_alive: KeepAlive::default(),
126 tcp_nodelay: None,
127 client_request_timeout: Duration::from_secs(5),
128 client_disconnect_timeout: Duration::from_secs(1),
129 h1_allow_half_closed: true,
130 h1_write_buffer_size: None,
131 h2_initial_window_size: None,
132 h2_initial_connection_window_size: None,
133 tls_handshake_timeout: None,
134 })),
135 backlog: 1024,
136 sockets: Vec::new(),
137 builder,
138 graceful_shutdown_signal,
139 on_connect_fn: None,
140 _phantom: PhantomData,
141 }
142 }
143
144 pub fn workers(mut self, num: usize) -> Self {
159 self.builder = self.builder.workers(num);
160 self
161 }
162
163 pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
167 self.config.lock().unwrap().keep_alive = val.into();
168 self
169 }
170
171 pub fn tcp_nodelay(self, enabled: bool) -> Self {
176 self.config.lock().unwrap().tcp_nodelay = Some(enabled);
177 self
178 }
179
180 pub fn backlog(mut self, backlog: u32) -> Self {
190 self.backlog = backlog;
191 self.builder = self.builder.backlog(backlog);
192 self
193 }
194
195 pub fn max_connections(mut self, num: usize) -> Self {
202 self.builder = self.builder.max_concurrent_connections(num);
203 self
204 }
205
206 #[allow(unused_variables)]
213 pub fn max_connection_rate(self, num: usize) -> Self {
214 #[cfg(feature = "__tls")]
215 actix_tls::accept::max_concurrent_tls_connect(num);
216 self
217 }
218
219 pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
225 self.builder = self.builder.worker_max_blocking_threads(num);
226 self
227 }
228
229 pub fn client_request_timeout(self, dur: Duration) -> Self {
238 self.config.lock().unwrap().client_request_timeout = dur;
239 self
240 }
241
242 #[doc(hidden)]
243 #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
244 pub fn client_timeout(self, dur: Duration) -> Self {
245 self.client_request_timeout(dur)
246 }
247
248 pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
257 self.config.lock().unwrap().client_disconnect_timeout = dur;
258 self
259 }
260
261 #[cfg(feature = "__tls")]
268 pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
269 self.config
270 .lock()
271 .unwrap()
272 .tls_handshake_timeout
273 .replace(dur);
274
275 self
276 }
277
278 #[doc(hidden)]
279 #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
280 pub fn client_shutdown(self, dur: u64) -> Self {
281 self.client_disconnect_timeout(Duration::from_millis(dur))
282 }
283
284 pub fn h1_allow_half_closed(self, allow: bool) -> Self {
292 self.config.lock().unwrap().h1_allow_half_closed = allow;
293 self
294 }
295
296 pub fn h1_write_buffer_size(self, size: usize) -> Self {
306 assert!(
307 size > 0,
308 "HTTP/1 write buffer size must be greater than zero"
309 );
310
311 self.config.lock().unwrap().h1_write_buffer_size = Some(size);
312 self
313 }
314
315 #[cfg(feature = "http2")]
322 pub fn h2_initial_window_size(self, size: u32) -> Self {
323 self.config.lock().unwrap().h2_initial_window_size = Some(size);
324 self
325 }
326
327 #[cfg(feature = "http2")]
334 pub fn h2_initial_connection_window_size(self, size: u32) -> Self {
335 self.config
336 .lock()
337 .unwrap()
338 .h2_initial_connection_window_size = Some(size);
339 self
340 }
341
342 pub fn on_connect<CB>(mut self, f: CB) -> HttpServer<F, I, S, B>
366 where
367 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
368 {
369 self.on_connect_fn = Some(Arc::new(f));
370 self
371 }
372
373 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
380 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
381 self
382 }
383
384 pub fn system_exit(mut self) -> Self {
388 self.builder = self.builder.system_exit();
389 self
390 }
391
392 pub fn disable_signals(mut self) -> Self {
394 self.builder = self.builder.disable_signals();
395 self
396 }
397
398 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
422 where
423 Fut: Future<Output = ()> + Send + 'static,
424 {
425 self.builder = self.builder.shutdown_signal(shutdown_signal);
426 self
427 }
428
429 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
436 self.builder = self.builder.shutdown_timeout(sec);
437 self
438 }
439
440 pub fn addrs(&self) -> Vec<net::SocketAddr> {
442 self.sockets.iter().map(|s| s.addr).collect()
443 }
444
445 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
451 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
452 }
453
454 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
509 let sockets = bind_addrs(addrs, self.backlog)?;
510
511 for lst in sockets {
512 self = self.listen(lst)?;
513 }
514
515 Ok(self)
516 }
517
518 #[cfg(feature = "http2")]
523 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
524 let sockets = bind_addrs(addrs, self.backlog)?;
525
526 for lst in sockets {
527 self = self.listen_auto_h2c(lst)?;
528 }
529
530 Ok(self)
531 }
532
533 #[cfg(feature = "rustls-0_20")]
541 pub fn bind_rustls<A: net::ToSocketAddrs>(
542 mut self,
543 addrs: A,
544 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
545 ) -> io::Result<Self> {
546 let sockets = bind_addrs(addrs, self.backlog)?;
547 for lst in sockets {
548 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
549 }
550 Ok(self)
551 }
552
553 #[cfg(feature = "rustls-0_21")]
561 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
562 mut self,
563 addrs: A,
564 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
565 ) -> io::Result<Self> {
566 let sockets = bind_addrs(addrs, self.backlog)?;
567 for lst in sockets {
568 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
569 }
570 Ok(self)
571 }
572
573 #[cfg(feature = "rustls-0_22")]
581 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
582 mut self,
583 addrs: A,
584 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
585 ) -> io::Result<Self> {
586 let sockets = bind_addrs(addrs, self.backlog)?;
587 for lst in sockets {
588 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
589 }
590 Ok(self)
591 }
592
593 #[cfg(feature = "rustls-0_23")]
601 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
602 mut self,
603 addrs: A,
604 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
605 ) -> io::Result<Self> {
606 let sockets = bind_addrs(addrs, self.backlog)?;
607 for lst in sockets {
608 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
609 }
610 Ok(self)
611 }
612
613 #[cfg(feature = "openssl")]
621 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
622 where
623 A: net::ToSocketAddrs,
624 {
625 let sockets = bind_addrs(addrs, self.backlog)?;
626 let acceptor = openssl_acceptor(builder)?;
627
628 for lst in sockets {
629 self = self.listen_openssl_inner(lst, acceptor.clone())?;
630 }
631
632 Ok(self)
633 }
634
635 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
640 let cfg = Arc::clone(&self.config);
641 let factory = self.factory.clone();
642 let addr = lst.local_addr().unwrap();
643
644 self.sockets.push(Socket {
645 addr,
646 scheme: "http",
647 });
648
649 let on_connect_fn = self.on_connect_fn.clone();
650 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
651
652 self.builder =
653 self.builder
654 .listen(format!("actix-web-service-{}", addr), lst, move || {
655 let cfg = cfg.lock().unwrap();
656 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
657 let shutdown_signal = graceful_shutdown_signal.clone();
658
659 let mut svc = HttpService::build()
660 .graceful_shutdown_signal(move || {
661 let signal = shutdown_signal.clone();
662 async move { signal.notified().await }
663 })
664 .keep_alive(cfg.keep_alive)
665 .client_request_timeout(cfg.client_request_timeout)
666 .client_disconnect_timeout(cfg.client_disconnect_timeout)
667 .h1_allow_half_closed(cfg.h1_allow_half_closed)
668 .local_addr(addr);
669
670 if let Some(enabled) = cfg.tcp_nodelay {
671 svc = svc.tcp_nodelay(enabled);
672 }
673
674 if let Some(size) = cfg.h1_write_buffer_size {
675 svc = svc.h1_write_buffer_size(size);
676 }
677
678 if let Some(val) = cfg.h2_initial_window_size {
679 svc = svc.h2_initial_window_size(val);
680 }
681
682 if let Some(val) = cfg.h2_initial_connection_window_size {
683 svc = svc.h2_initial_connection_window_size(val);
684 }
685
686 if let Some(handler) = on_connect_fn.clone() {
687 svc =
688 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
689 };
690
691 let fac = factory()
692 .into_factory()
693 .map_err(|err| err.into().error_response());
694
695 svc.finish(map_config(fac, move |_| {
696 AppConfig::new(false, host.clone(), addr)
697 }))
698 .tcp()
699 })?;
700
701 Ok(self)
702 }
703
704 #[cfg(feature = "http2")]
706 pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
707 let cfg = Arc::clone(&self.config);
708 let factory = self.factory.clone();
709 let addr = lst.local_addr().unwrap();
710
711 self.sockets.push(Socket {
712 addr,
713 scheme: "http",
714 });
715
716 let on_connect_fn = self.on_connect_fn.clone();
717 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
718
719 self.builder =
720 self.builder
721 .listen(format!("actix-web-service-{}", addr), lst, move || {
722 let cfg = cfg.lock().unwrap();
723 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
724 let shutdown_signal = graceful_shutdown_signal.clone();
725
726 let mut svc = HttpService::build()
727 .graceful_shutdown_signal(move || {
728 let signal = shutdown_signal.clone();
729 async move { signal.notified().await }
730 })
731 .keep_alive(cfg.keep_alive)
732 .client_request_timeout(cfg.client_request_timeout)
733 .client_disconnect_timeout(cfg.client_disconnect_timeout)
734 .h1_allow_half_closed(cfg.h1_allow_half_closed)
735 .local_addr(addr);
736
737 if let Some(enabled) = cfg.tcp_nodelay {
738 svc = svc.tcp_nodelay(enabled);
739 }
740
741 if let Some(size) = cfg.h1_write_buffer_size {
742 svc = svc.h1_write_buffer_size(size);
743 }
744
745 if let Some(val) = cfg.h2_initial_window_size {
746 svc = svc.h2_initial_window_size(val);
747 }
748
749 if let Some(val) = cfg.h2_initial_connection_window_size {
750 svc = svc.h2_initial_connection_window_size(val);
751 }
752
753 if let Some(handler) = on_connect_fn.clone() {
754 svc =
755 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
756 };
757
758 let fac = factory()
759 .into_factory()
760 .map_err(|err| err.into().error_response());
761
762 svc.finish(map_config(fac, move |_| {
763 AppConfig::new(false, host.clone(), addr)
764 }))
765 .tcp_auto_h2c()
766 })?;
767
768 Ok(self)
769 }
770
771 #[cfg(feature = "rustls-0_20")]
779 pub fn listen_rustls(
780 self,
781 lst: net::TcpListener,
782 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
783 ) -> io::Result<Self> {
784 self.listen_rustls_0_20_inner(lst, config)
785 }
786
787 #[cfg(feature = "rustls-0_21")]
795 pub fn listen_rustls_0_21(
796 self,
797 lst: net::TcpListener,
798 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
799 ) -> io::Result<Self> {
800 self.listen_rustls_0_21_inner(lst, config)
801 }
802
803 #[cfg(feature = "rustls-0_20")]
804 fn listen_rustls_0_20_inner(
805 mut self,
806 lst: net::TcpListener,
807 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
808 ) -> io::Result<Self> {
809 let factory = self.factory.clone();
810 let cfg = Arc::clone(&self.config);
811 let addr = lst.local_addr().unwrap();
812 self.sockets.push(Socket {
813 addr,
814 scheme: "https",
815 });
816
817 let on_connect_fn = self.on_connect_fn.clone();
818 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
819
820 self.builder =
821 self.builder
822 .listen(format!("actix-web-service-{}", addr), lst, move || {
823 let c = cfg.lock().unwrap();
824 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
825 let shutdown_signal = graceful_shutdown_signal.clone();
826
827 let mut svc = HttpService::build()
828 .graceful_shutdown_signal(move || {
829 let signal = shutdown_signal.clone();
830 async move { signal.notified().await }
831 })
832 .keep_alive(c.keep_alive)
833 .client_request_timeout(c.client_request_timeout)
834 .h1_allow_half_closed(c.h1_allow_half_closed)
835 .client_disconnect_timeout(c.client_disconnect_timeout);
836
837 if let Some(enabled) = c.tcp_nodelay {
838 svc = svc.tcp_nodelay(enabled);
839 }
840
841 if let Some(size) = c.h1_write_buffer_size {
842 svc = svc.h1_write_buffer_size(size);
843 }
844
845 if let Some(val) = c.h2_initial_window_size {
846 svc = svc.h2_initial_window_size(val);
847 }
848
849 if let Some(val) = c.h2_initial_connection_window_size {
850 svc = svc.h2_initial_connection_window_size(val);
851 }
852
853 if let Some(handler) = on_connect_fn.clone() {
854 svc = svc
855 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
856 };
857
858 let fac = factory()
859 .into_factory()
860 .map_err(|err| err.into().error_response());
861
862 let acceptor_config = match c.tls_handshake_timeout {
863 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
864 None => TlsAcceptorConfig::default(),
865 };
866
867 svc.finish(map_config(fac, move |_| {
868 AppConfig::new(true, host.clone(), addr)
869 }))
870 .rustls_with_config(config.clone(), acceptor_config)
871 })?;
872
873 Ok(self)
874 }
875
876 #[cfg(feature = "rustls-0_21")]
877 fn listen_rustls_0_21_inner(
878 mut self,
879 lst: net::TcpListener,
880 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
881 ) -> io::Result<Self> {
882 let factory = self.factory.clone();
883 let cfg = Arc::clone(&self.config);
884 let addr = lst.local_addr().unwrap();
885 self.sockets.push(Socket {
886 addr,
887 scheme: "https",
888 });
889
890 let on_connect_fn = self.on_connect_fn.clone();
891 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
892
893 self.builder =
894 self.builder
895 .listen(format!("actix-web-service-{}", addr), lst, move || {
896 let c = cfg.lock().unwrap();
897 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
898 let shutdown_signal = graceful_shutdown_signal.clone();
899
900 let mut svc = HttpService::build()
901 .graceful_shutdown_signal(move || {
902 let signal = shutdown_signal.clone();
903 async move { signal.notified().await }
904 })
905 .keep_alive(c.keep_alive)
906 .client_request_timeout(c.client_request_timeout)
907 .h1_allow_half_closed(c.h1_allow_half_closed)
908 .client_disconnect_timeout(c.client_disconnect_timeout);
909
910 if let Some(enabled) = c.tcp_nodelay {
911 svc = svc.tcp_nodelay(enabled);
912 }
913
914 if let Some(size) = c.h1_write_buffer_size {
915 svc = svc.h1_write_buffer_size(size);
916 }
917
918 if let Some(val) = c.h2_initial_window_size {
919 svc = svc.h2_initial_window_size(val);
920 }
921
922 if let Some(val) = c.h2_initial_connection_window_size {
923 svc = svc.h2_initial_connection_window_size(val);
924 }
925
926 if let Some(handler) = on_connect_fn.clone() {
927 svc = svc
928 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
929 };
930
931 let fac = factory()
932 .into_factory()
933 .map_err(|err| err.into().error_response());
934
935 let acceptor_config = match c.tls_handshake_timeout {
936 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
937 None => TlsAcceptorConfig::default(),
938 };
939
940 svc.finish(map_config(fac, move |_| {
941 AppConfig::new(true, host.clone(), addr)
942 }))
943 .rustls_021_with_config(config.clone(), acceptor_config)
944 })?;
945
946 Ok(self)
947 }
948
949 #[cfg(feature = "rustls-0_22")]
957 pub fn listen_rustls_0_22(
958 self,
959 lst: net::TcpListener,
960 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
961 ) -> io::Result<Self> {
962 self.listen_rustls_0_22_inner(lst, config)
963 }
964
965 #[cfg(feature = "rustls-0_22")]
966 fn listen_rustls_0_22_inner(
967 mut self,
968 lst: net::TcpListener,
969 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
970 ) -> io::Result<Self> {
971 let factory = self.factory.clone();
972 let cfg = Arc::clone(&self.config);
973 let addr = lst.local_addr().unwrap();
974 self.sockets.push(Socket {
975 addr,
976 scheme: "https",
977 });
978
979 let on_connect_fn = self.on_connect_fn.clone();
980 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
981
982 self.builder =
983 self.builder
984 .listen(format!("actix-web-service-{}", addr), lst, move || {
985 let c = cfg.lock().unwrap();
986 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
987 let shutdown_signal = graceful_shutdown_signal.clone();
988
989 let mut svc = HttpService::build()
990 .graceful_shutdown_signal(move || {
991 let signal = shutdown_signal.clone();
992 async move { signal.notified().await }
993 })
994 .keep_alive(c.keep_alive)
995 .client_request_timeout(c.client_request_timeout)
996 .h1_allow_half_closed(c.h1_allow_half_closed)
997 .client_disconnect_timeout(c.client_disconnect_timeout);
998
999 if let Some(enabled) = c.tcp_nodelay {
1000 svc = svc.tcp_nodelay(enabled);
1001 }
1002
1003 if let Some(size) = c.h1_write_buffer_size {
1004 svc = svc.h1_write_buffer_size(size);
1005 }
1006
1007 if let Some(val) = c.h2_initial_window_size {
1008 svc = svc.h2_initial_window_size(val);
1009 }
1010
1011 if let Some(val) = c.h2_initial_connection_window_size {
1012 svc = svc.h2_initial_connection_window_size(val);
1013 }
1014
1015 if let Some(handler) = on_connect_fn.clone() {
1016 svc = svc
1017 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1018 };
1019
1020 let fac = factory()
1021 .into_factory()
1022 .map_err(|err| err.into().error_response());
1023
1024 let acceptor_config = match c.tls_handshake_timeout {
1025 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1026 None => TlsAcceptorConfig::default(),
1027 };
1028
1029 svc.finish(map_config(fac, move |_| {
1030 AppConfig::new(true, host.clone(), addr)
1031 }))
1032 .rustls_0_22_with_config(config.clone(), acceptor_config)
1033 })?;
1034
1035 Ok(self)
1036 }
1037
1038 #[cfg(feature = "rustls-0_23")]
1046 pub fn listen_rustls_0_23(
1047 self,
1048 lst: net::TcpListener,
1049 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1050 ) -> io::Result<Self> {
1051 self.listen_rustls_0_23_inner(lst, config)
1052 }
1053
1054 #[cfg(feature = "rustls-0_23")]
1055 fn listen_rustls_0_23_inner(
1056 mut self,
1057 lst: net::TcpListener,
1058 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1059 ) -> io::Result<Self> {
1060 let factory = self.factory.clone();
1061 let cfg = Arc::clone(&self.config);
1062 let addr = lst.local_addr().unwrap();
1063 self.sockets.push(Socket {
1064 addr,
1065 scheme: "https",
1066 });
1067
1068 let on_connect_fn = self.on_connect_fn.clone();
1069 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1070
1071 self.builder =
1072 self.builder
1073 .listen(format!("actix-web-service-{}", addr), lst, move || {
1074 let c = cfg.lock().unwrap();
1075 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1076 let shutdown_signal = graceful_shutdown_signal.clone();
1077
1078 let mut svc = HttpService::build()
1079 .graceful_shutdown_signal(move || {
1080 let signal = shutdown_signal.clone();
1081 async move { signal.notified().await }
1082 })
1083 .keep_alive(c.keep_alive)
1084 .client_request_timeout(c.client_request_timeout)
1085 .h1_allow_half_closed(c.h1_allow_half_closed)
1086 .client_disconnect_timeout(c.client_disconnect_timeout);
1087
1088 if let Some(enabled) = c.tcp_nodelay {
1089 svc = svc.tcp_nodelay(enabled);
1090 }
1091
1092 if let Some(size) = c.h1_write_buffer_size {
1093 svc = svc.h1_write_buffer_size(size);
1094 }
1095
1096 if let Some(val) = c.h2_initial_window_size {
1097 svc = svc.h2_initial_window_size(val);
1098 }
1099
1100 if let Some(val) = c.h2_initial_connection_window_size {
1101 svc = svc.h2_initial_connection_window_size(val);
1102 }
1103
1104 if let Some(handler) = on_connect_fn.clone() {
1105 svc = svc
1106 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1107 };
1108
1109 let fac = factory()
1110 .into_factory()
1111 .map_err(|err| err.into().error_response());
1112
1113 let acceptor_config = match c.tls_handshake_timeout {
1114 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1115 None => TlsAcceptorConfig::default(),
1116 };
1117
1118 svc.finish(map_config(fac, move |_| {
1119 AppConfig::new(true, host.clone(), addr)
1120 }))
1121 .rustls_0_23_with_config(config.clone(), acceptor_config)
1122 })?;
1123
1124 Ok(self)
1125 }
1126
1127 #[cfg(feature = "openssl")]
1134 pub fn listen_openssl(
1135 self,
1136 lst: net::TcpListener,
1137 builder: SslAcceptorBuilder,
1138 ) -> io::Result<Self> {
1139 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1140 }
1141
1142 #[cfg(feature = "openssl")]
1143 fn listen_openssl_inner(
1144 mut self,
1145 lst: net::TcpListener,
1146 acceptor: SslAcceptor,
1147 ) -> io::Result<Self> {
1148 let factory = self.factory.clone();
1149 let cfg = Arc::clone(&self.config);
1150 let addr = lst.local_addr().unwrap();
1151
1152 self.sockets.push(Socket {
1153 addr,
1154 scheme: "https",
1155 });
1156
1157 let on_connect_fn = self.on_connect_fn.clone();
1158 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1159
1160 self.builder =
1161 self.builder
1162 .listen(format!("actix-web-service-{}", addr), lst, move || {
1163 let c = cfg.lock().unwrap();
1164 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1165 let shutdown_signal = graceful_shutdown_signal.clone();
1166
1167 let mut svc = HttpService::build()
1168 .graceful_shutdown_signal(move || {
1169 let signal = shutdown_signal.clone();
1170 async move { signal.notified().await }
1171 })
1172 .keep_alive(c.keep_alive)
1173 .client_request_timeout(c.client_request_timeout)
1174 .client_disconnect_timeout(c.client_disconnect_timeout)
1175 .h1_allow_half_closed(c.h1_allow_half_closed)
1176 .local_addr(addr);
1177
1178 if let Some(enabled) = c.tcp_nodelay {
1179 svc = svc.tcp_nodelay(enabled);
1180 }
1181
1182 if let Some(size) = c.h1_write_buffer_size {
1183 svc = svc.h1_write_buffer_size(size);
1184 }
1185
1186 if let Some(val) = c.h2_initial_window_size {
1187 svc = svc.h2_initial_window_size(val);
1188 }
1189
1190 if let Some(val) = c.h2_initial_connection_window_size {
1191 svc = svc.h2_initial_connection_window_size(val);
1192 }
1193
1194 if let Some(handler) = on_connect_fn.clone() {
1195 svc = svc
1196 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1197 };
1198
1199 let fac = factory()
1200 .into_factory()
1201 .map_err(|err| err.into().error_response());
1202
1203 #[allow(clippy::significant_drop_in_scrutinee)]
1205 let acceptor_config = match c.tls_handshake_timeout {
1206 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1207 None => TlsAcceptorConfig::default(),
1208 };
1209
1210 svc.finish(map_config(fac, move |_| {
1211 AppConfig::new(true, host.clone(), addr)
1212 }))
1213 .openssl_with_config(acceptor.clone(), acceptor_config)
1214 })?;
1215
1216 Ok(self)
1217 }
1218
1219 #[cfg(unix)]
1221 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1222 where
1223 A: AsRef<std::path::Path>,
1224 {
1225 use actix_http::Protocol;
1226 use actix_service::{fn_service, ServiceFactoryExt as _};
1227 use tokio::net::UnixStream;
1228
1229 let cfg = Arc::clone(&self.config);
1230 let factory = self.factory.clone();
1231 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1232 let socket_addr =
1233 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1234
1235 self.sockets.push(Socket {
1236 scheme: "http",
1237 addr: socket_addr,
1238 });
1239
1240 self.builder = self.builder.bind_uds(
1241 format!("actix-web-service-{:?}", uds_path.as_ref()),
1242 uds_path,
1243 move || {
1244 let c = cfg.lock().unwrap();
1245 let config = AppConfig::new(
1246 false,
1247 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1248 socket_addr,
1249 );
1250
1251 let fac = factory()
1252 .into_factory()
1253 .map_err(|err| err.into().error_response());
1254
1255 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1256 let shutdown_signal = graceful_shutdown_signal.clone();
1257 let mut svc = HttpService::build()
1258 .graceful_shutdown_signal(move || {
1259 let signal = shutdown_signal.clone();
1260 async move { signal.notified().await }
1261 })
1262 .keep_alive(c.keep_alive)
1263 .client_request_timeout(c.client_request_timeout)
1264 .client_disconnect_timeout(c.client_disconnect_timeout)
1265 .h1_allow_half_closed(c.h1_allow_half_closed);
1266
1267 if let Some(size) = c.h1_write_buffer_size {
1268 svc = svc.h1_write_buffer_size(size);
1269 }
1270
1271 svc.finish(map_config(fac, move |_| config.clone()))
1272 })
1273 },
1274 )?;
1275
1276 Ok(self)
1277 }
1278
1279 #[cfg(unix)]
1281 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1282 use actix_http::Protocol;
1283 use actix_service::{fn_service, ServiceFactoryExt as _};
1284 use tokio::net::UnixStream;
1285
1286 let cfg = Arc::clone(&self.config);
1287 let factory = self.factory.clone();
1288 let socket_addr =
1289 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1290
1291 self.sockets.push(Socket {
1292 scheme: "http",
1293 addr: socket_addr,
1294 });
1295
1296 let addr = lst.local_addr()?;
1297 let name = format!("actix-web-service-{:?}", addr);
1298 let on_connect_fn = self.on_connect_fn.clone();
1299 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1300
1301 self.builder = self.builder.listen_uds(name, lst, move || {
1302 let c = cfg.lock().unwrap();
1303 let config = AppConfig::new(
1304 false,
1305 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1306 socket_addr,
1307 );
1308
1309 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1310 let shutdown_signal = graceful_shutdown_signal.clone();
1311 let mut svc = HttpService::build()
1312 .graceful_shutdown_signal(move || {
1313 let signal = shutdown_signal.clone();
1314 async move { signal.notified().await }
1315 })
1316 .keep_alive(c.keep_alive)
1317 .client_request_timeout(c.client_request_timeout)
1318 .h1_allow_half_closed(c.h1_allow_half_closed)
1319 .client_disconnect_timeout(c.client_disconnect_timeout);
1320
1321 if let Some(handler) = on_connect_fn.clone() {
1322 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1323 }
1324
1325 if let Some(size) = c.h1_write_buffer_size {
1326 svc = svc.h1_write_buffer_size(size);
1327 }
1328
1329 let fac = factory()
1330 .into_factory()
1331 .map_err(|err| err.into().error_response());
1332
1333 svc.finish(map_config(fac, move |_| config.clone()))
1334 })
1335 })?;
1336 Ok(self)
1337 }
1338}
1339
1340impl<F, I, S, B> HttpServer<F, I, S, B>
1341where
1342 F: Fn() -> I + Send + Clone + 'static,
1343 I: IntoServiceFactory<S, Request>,
1344 S: ServiceFactory<Request, Config = AppConfig>,
1345 S::Error: Into<Error>,
1346 S::InitError: fmt::Debug,
1347 S::Response: Into<Response<B>>,
1348 S::Service: 'static,
1349 B: MessageBody,
1350{
1351 pub fn run(self) -> Server {
1364 self.builder.run()
1365 }
1366}
1367
1368fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1370 let mut err = None;
1371 let mut success = false;
1372 let mut sockets = Vec::new();
1373
1374 for addr in addrs.to_socket_addrs()? {
1375 match create_tcp_listener(addr, backlog) {
1376 Ok(lst) => {
1377 success = true;
1378 sockets.push(lst);
1379 }
1380 Err(error) => err = Some(error),
1381 }
1382 }
1383
1384 if success {
1385 Ok(sockets)
1386 } else if let Some(err) = err.take() {
1387 Err(err)
1388 } else {
1389 Err(io::Error::other("Could not bind to address"))
1390 }
1391}
1392
1393fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1395 use socket2::{Domain, Protocol, Socket, Type};
1396 let domain = Domain::for_address(addr);
1397 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1398 #[cfg(not(windows))]
1399 {
1400 socket.set_reuse_address(true)?;
1401 }
1402 #[cfg(windows)]
1405 if addr.is_ipv6() {
1406 if let Err(err) = socket.set_only_v6(false) {
1407 log::warn!("failed to set IPV6_V6ONLY=false: {err}");
1408 }
1409 }
1410 socket.bind(&addr.into())?;
1411 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1413 socket.listen(backlog)?;
1414 Ok(net::TcpListener::from(socket))
1415}
1416
1417#[cfg(feature = "openssl")]
1419fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1420 builder.set_alpn_select_callback(|_, protocols| {
1421 const H11: &[u8] = b"\x08http/1.1";
1422
1423 #[cfg(feature = "http2")]
1424 {
1425 const H2: &[u8] = b"\x02h2";
1426
1427 if protocols.windows(3).any(|window| window == H2) {
1428 return Ok(b"h2");
1429 }
1430 }
1431
1432 if protocols.windows(9).any(|window| window == H11) {
1433 Ok(b"http/1.1")
1434 } else {
1435 Err(AlpnError::NOACK)
1436 }
1437 });
1438
1439 #[cfg(feature = "http2")]
1440 let protos = b"\x08http/1.1\x02h2";
1441 #[cfg(not(feature = "http2"))]
1442 let protos = b"\x08http/1.1";
1443 builder.set_alpn_protos(protos)?;
1444
1445 Ok(builder.build())
1446}