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>
361 where
362 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
363 {
364 self.on_connect_fn = Some(Arc::new(f));
365 self
366 }
367
368 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
375 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
376 self
377 }
378
379 pub fn system_exit(mut self) -> Self {
383 self.builder = self.builder.system_exit();
384 self
385 }
386
387 pub fn disable_signals(mut self) -> Self {
389 self.builder = self.builder.disable_signals();
390 self
391 }
392
393 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
417 where
418 Fut: Future<Output = ()> + Send + 'static,
419 {
420 self.builder = self.builder.shutdown_signal(shutdown_signal);
421 self
422 }
423
424 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
431 self.builder = self.builder.shutdown_timeout(sec);
432 self
433 }
434
435 pub fn addrs(&self) -> Vec<net::SocketAddr> {
437 self.sockets.iter().map(|s| s.addr).collect()
438 }
439
440 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
446 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
447 }
448
449 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
504 let sockets = bind_addrs(addrs, self.backlog)?;
505
506 for lst in sockets {
507 self = self.listen(lst)?;
508 }
509
510 Ok(self)
511 }
512
513 #[cfg(feature = "http2")]
518 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
519 let sockets = bind_addrs(addrs, self.backlog)?;
520
521 for lst in sockets {
522 self = self.listen_auto_h2c(lst)?;
523 }
524
525 Ok(self)
526 }
527
528 #[cfg(feature = "rustls-0_20")]
536 pub fn bind_rustls<A: net::ToSocketAddrs>(
537 mut self,
538 addrs: A,
539 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
540 ) -> io::Result<Self> {
541 let sockets = bind_addrs(addrs, self.backlog)?;
542 for lst in sockets {
543 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
544 }
545 Ok(self)
546 }
547
548 #[cfg(feature = "rustls-0_21")]
556 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
557 mut self,
558 addrs: A,
559 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
560 ) -> io::Result<Self> {
561 let sockets = bind_addrs(addrs, self.backlog)?;
562 for lst in sockets {
563 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
564 }
565 Ok(self)
566 }
567
568 #[cfg(feature = "rustls-0_22")]
576 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
577 mut self,
578 addrs: A,
579 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
580 ) -> io::Result<Self> {
581 let sockets = bind_addrs(addrs, self.backlog)?;
582 for lst in sockets {
583 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
584 }
585 Ok(self)
586 }
587
588 #[cfg(feature = "rustls-0_23")]
596 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
597 mut self,
598 addrs: A,
599 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
600 ) -> io::Result<Self> {
601 let sockets = bind_addrs(addrs, self.backlog)?;
602 for lst in sockets {
603 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
604 }
605 Ok(self)
606 }
607
608 #[cfg(feature = "openssl")]
616 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
617 where
618 A: net::ToSocketAddrs,
619 {
620 let sockets = bind_addrs(addrs, self.backlog)?;
621 let acceptor = openssl_acceptor(builder)?;
622
623 for lst in sockets {
624 self = self.listen_openssl_inner(lst, acceptor.clone())?;
625 }
626
627 Ok(self)
628 }
629
630 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
635 let cfg = Arc::clone(&self.config);
636 let factory = self.factory.clone();
637 let addr = lst.local_addr().unwrap();
638
639 self.sockets.push(Socket {
640 addr,
641 scheme: "http",
642 });
643
644 let on_connect_fn = self.on_connect_fn.clone();
645 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
646
647 self.builder =
648 self.builder
649 .listen(format!("actix-web-service-{}", addr), lst, move || {
650 let cfg = cfg.lock().unwrap();
651 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
652 let shutdown_signal = graceful_shutdown_signal.clone();
653
654 let mut svc = HttpService::build()
655 .graceful_shutdown_signal(move || {
656 let signal = shutdown_signal.clone();
657 async move { signal.notified().await }
658 })
659 .keep_alive(cfg.keep_alive)
660 .client_request_timeout(cfg.client_request_timeout)
661 .client_disconnect_timeout(cfg.client_disconnect_timeout)
662 .h1_allow_half_closed(cfg.h1_allow_half_closed)
663 .local_addr(addr);
664
665 if let Some(enabled) = cfg.tcp_nodelay {
666 svc = svc.tcp_nodelay(enabled);
667 }
668
669 if let Some(size) = cfg.h1_write_buffer_size {
670 svc = svc.h1_write_buffer_size(size);
671 }
672
673 if let Some(val) = cfg.h2_initial_window_size {
674 svc = svc.h2_initial_window_size(val);
675 }
676
677 if let Some(val) = cfg.h2_initial_connection_window_size {
678 svc = svc.h2_initial_connection_window_size(val);
679 }
680
681 if let Some(handler) = on_connect_fn.clone() {
682 svc =
683 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
684 };
685
686 let fac = factory()
687 .into_factory()
688 .map_err(|err| err.into().error_response());
689
690 svc.finish(map_config(fac, move |_| {
691 AppConfig::new(false, host.clone(), addr)
692 }))
693 .tcp()
694 })?;
695
696 Ok(self)
697 }
698
699 #[cfg(feature = "http2")]
701 pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
702 let cfg = Arc::clone(&self.config);
703 let factory = self.factory.clone();
704 let addr = lst.local_addr().unwrap();
705
706 self.sockets.push(Socket {
707 addr,
708 scheme: "http",
709 });
710
711 let on_connect_fn = self.on_connect_fn.clone();
712 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
713
714 self.builder =
715 self.builder
716 .listen(format!("actix-web-service-{}", addr), lst, move || {
717 let cfg = cfg.lock().unwrap();
718 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
719 let shutdown_signal = graceful_shutdown_signal.clone();
720
721 let mut svc = HttpService::build()
722 .graceful_shutdown_signal(move || {
723 let signal = shutdown_signal.clone();
724 async move { signal.notified().await }
725 })
726 .keep_alive(cfg.keep_alive)
727 .client_request_timeout(cfg.client_request_timeout)
728 .client_disconnect_timeout(cfg.client_disconnect_timeout)
729 .h1_allow_half_closed(cfg.h1_allow_half_closed)
730 .local_addr(addr);
731
732 if let Some(enabled) = cfg.tcp_nodelay {
733 svc = svc.tcp_nodelay(enabled);
734 }
735
736 if let Some(size) = cfg.h1_write_buffer_size {
737 svc = svc.h1_write_buffer_size(size);
738 }
739
740 if let Some(val) = cfg.h2_initial_window_size {
741 svc = svc.h2_initial_window_size(val);
742 }
743
744 if let Some(val) = cfg.h2_initial_connection_window_size {
745 svc = svc.h2_initial_connection_window_size(val);
746 }
747
748 if let Some(handler) = on_connect_fn.clone() {
749 svc =
750 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
751 };
752
753 let fac = factory()
754 .into_factory()
755 .map_err(|err| err.into().error_response());
756
757 svc.finish(map_config(fac, move |_| {
758 AppConfig::new(false, host.clone(), addr)
759 }))
760 .tcp_auto_h2c()
761 })?;
762
763 Ok(self)
764 }
765
766 #[cfg(feature = "rustls-0_20")]
774 pub fn listen_rustls(
775 self,
776 lst: net::TcpListener,
777 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
778 ) -> io::Result<Self> {
779 self.listen_rustls_0_20_inner(lst, config)
780 }
781
782 #[cfg(feature = "rustls-0_21")]
790 pub fn listen_rustls_0_21(
791 self,
792 lst: net::TcpListener,
793 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
794 ) -> io::Result<Self> {
795 self.listen_rustls_0_21_inner(lst, config)
796 }
797
798 #[cfg(feature = "rustls-0_20")]
799 fn listen_rustls_0_20_inner(
800 mut self,
801 lst: net::TcpListener,
802 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
803 ) -> io::Result<Self> {
804 let factory = self.factory.clone();
805 let cfg = Arc::clone(&self.config);
806 let addr = lst.local_addr().unwrap();
807 self.sockets.push(Socket {
808 addr,
809 scheme: "https",
810 });
811
812 let on_connect_fn = self.on_connect_fn.clone();
813 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
814
815 self.builder =
816 self.builder
817 .listen(format!("actix-web-service-{}", addr), lst, move || {
818 let c = cfg.lock().unwrap();
819 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
820 let shutdown_signal = graceful_shutdown_signal.clone();
821
822 let mut svc = HttpService::build()
823 .graceful_shutdown_signal(move || {
824 let signal = shutdown_signal.clone();
825 async move { signal.notified().await }
826 })
827 .keep_alive(c.keep_alive)
828 .client_request_timeout(c.client_request_timeout)
829 .h1_allow_half_closed(c.h1_allow_half_closed)
830 .client_disconnect_timeout(c.client_disconnect_timeout);
831
832 if let Some(enabled) = c.tcp_nodelay {
833 svc = svc.tcp_nodelay(enabled);
834 }
835
836 if let Some(size) = c.h1_write_buffer_size {
837 svc = svc.h1_write_buffer_size(size);
838 }
839
840 if let Some(val) = c.h2_initial_window_size {
841 svc = svc.h2_initial_window_size(val);
842 }
843
844 if let Some(val) = c.h2_initial_connection_window_size {
845 svc = svc.h2_initial_connection_window_size(val);
846 }
847
848 if let Some(handler) = on_connect_fn.clone() {
849 svc = svc
850 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
851 };
852
853 let fac = factory()
854 .into_factory()
855 .map_err(|err| err.into().error_response());
856
857 let acceptor_config = match c.tls_handshake_timeout {
858 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
859 None => TlsAcceptorConfig::default(),
860 };
861
862 svc.finish(map_config(fac, move |_| {
863 AppConfig::new(true, host.clone(), addr)
864 }))
865 .rustls_with_config(config.clone(), acceptor_config)
866 })?;
867
868 Ok(self)
869 }
870
871 #[cfg(feature = "rustls-0_21")]
872 fn listen_rustls_0_21_inner(
873 mut self,
874 lst: net::TcpListener,
875 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
876 ) -> io::Result<Self> {
877 let factory = self.factory.clone();
878 let cfg = Arc::clone(&self.config);
879 let addr = lst.local_addr().unwrap();
880 self.sockets.push(Socket {
881 addr,
882 scheme: "https",
883 });
884
885 let on_connect_fn = self.on_connect_fn.clone();
886 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
887
888 self.builder =
889 self.builder
890 .listen(format!("actix-web-service-{}", addr), lst, move || {
891 let c = cfg.lock().unwrap();
892 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
893 let shutdown_signal = graceful_shutdown_signal.clone();
894
895 let mut svc = HttpService::build()
896 .graceful_shutdown_signal(move || {
897 let signal = shutdown_signal.clone();
898 async move { signal.notified().await }
899 })
900 .keep_alive(c.keep_alive)
901 .client_request_timeout(c.client_request_timeout)
902 .h1_allow_half_closed(c.h1_allow_half_closed)
903 .client_disconnect_timeout(c.client_disconnect_timeout);
904
905 if let Some(enabled) = c.tcp_nodelay {
906 svc = svc.tcp_nodelay(enabled);
907 }
908
909 if let Some(size) = c.h1_write_buffer_size {
910 svc = svc.h1_write_buffer_size(size);
911 }
912
913 if let Some(val) = c.h2_initial_window_size {
914 svc = svc.h2_initial_window_size(val);
915 }
916
917 if let Some(val) = c.h2_initial_connection_window_size {
918 svc = svc.h2_initial_connection_window_size(val);
919 }
920
921 if let Some(handler) = on_connect_fn.clone() {
922 svc = svc
923 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
924 };
925
926 let fac = factory()
927 .into_factory()
928 .map_err(|err| err.into().error_response());
929
930 let acceptor_config = match c.tls_handshake_timeout {
931 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
932 None => TlsAcceptorConfig::default(),
933 };
934
935 svc.finish(map_config(fac, move |_| {
936 AppConfig::new(true, host.clone(), addr)
937 }))
938 .rustls_021_with_config(config.clone(), acceptor_config)
939 })?;
940
941 Ok(self)
942 }
943
944 #[cfg(feature = "rustls-0_22")]
952 pub fn listen_rustls_0_22(
953 self,
954 lst: net::TcpListener,
955 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
956 ) -> io::Result<Self> {
957 self.listen_rustls_0_22_inner(lst, config)
958 }
959
960 #[cfg(feature = "rustls-0_22")]
961 fn listen_rustls_0_22_inner(
962 mut self,
963 lst: net::TcpListener,
964 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
965 ) -> io::Result<Self> {
966 let factory = self.factory.clone();
967 let cfg = Arc::clone(&self.config);
968 let addr = lst.local_addr().unwrap();
969 self.sockets.push(Socket {
970 addr,
971 scheme: "https",
972 });
973
974 let on_connect_fn = self.on_connect_fn.clone();
975 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
976
977 self.builder =
978 self.builder
979 .listen(format!("actix-web-service-{}", addr), lst, move || {
980 let c = cfg.lock().unwrap();
981 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
982 let shutdown_signal = graceful_shutdown_signal.clone();
983
984 let mut svc = HttpService::build()
985 .graceful_shutdown_signal(move || {
986 let signal = shutdown_signal.clone();
987 async move { signal.notified().await }
988 })
989 .keep_alive(c.keep_alive)
990 .client_request_timeout(c.client_request_timeout)
991 .h1_allow_half_closed(c.h1_allow_half_closed)
992 .client_disconnect_timeout(c.client_disconnect_timeout);
993
994 if let Some(enabled) = c.tcp_nodelay {
995 svc = svc.tcp_nodelay(enabled);
996 }
997
998 if let Some(size) = c.h1_write_buffer_size {
999 svc = svc.h1_write_buffer_size(size);
1000 }
1001
1002 if let Some(val) = c.h2_initial_window_size {
1003 svc = svc.h2_initial_window_size(val);
1004 }
1005
1006 if let Some(val) = c.h2_initial_connection_window_size {
1007 svc = svc.h2_initial_connection_window_size(val);
1008 }
1009
1010 if let Some(handler) = on_connect_fn.clone() {
1011 svc = svc
1012 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1013 };
1014
1015 let fac = factory()
1016 .into_factory()
1017 .map_err(|err| err.into().error_response());
1018
1019 let acceptor_config = match c.tls_handshake_timeout {
1020 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1021 None => TlsAcceptorConfig::default(),
1022 };
1023
1024 svc.finish(map_config(fac, move |_| {
1025 AppConfig::new(true, host.clone(), addr)
1026 }))
1027 .rustls_0_22_with_config(config.clone(), acceptor_config)
1028 })?;
1029
1030 Ok(self)
1031 }
1032
1033 #[cfg(feature = "rustls-0_23")]
1041 pub fn listen_rustls_0_23(
1042 self,
1043 lst: net::TcpListener,
1044 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1045 ) -> io::Result<Self> {
1046 self.listen_rustls_0_23_inner(lst, config)
1047 }
1048
1049 #[cfg(feature = "rustls-0_23")]
1050 fn listen_rustls_0_23_inner(
1051 mut self,
1052 lst: net::TcpListener,
1053 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1054 ) -> io::Result<Self> {
1055 let factory = self.factory.clone();
1056 let cfg = Arc::clone(&self.config);
1057 let addr = lst.local_addr().unwrap();
1058 self.sockets.push(Socket {
1059 addr,
1060 scheme: "https",
1061 });
1062
1063 let on_connect_fn = self.on_connect_fn.clone();
1064 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1065
1066 self.builder =
1067 self.builder
1068 .listen(format!("actix-web-service-{}", addr), lst, move || {
1069 let c = cfg.lock().unwrap();
1070 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1071 let shutdown_signal = graceful_shutdown_signal.clone();
1072
1073 let mut svc = HttpService::build()
1074 .graceful_shutdown_signal(move || {
1075 let signal = shutdown_signal.clone();
1076 async move { signal.notified().await }
1077 })
1078 .keep_alive(c.keep_alive)
1079 .client_request_timeout(c.client_request_timeout)
1080 .h1_allow_half_closed(c.h1_allow_half_closed)
1081 .client_disconnect_timeout(c.client_disconnect_timeout);
1082
1083 if let Some(enabled) = c.tcp_nodelay {
1084 svc = svc.tcp_nodelay(enabled);
1085 }
1086
1087 if let Some(size) = c.h1_write_buffer_size {
1088 svc = svc.h1_write_buffer_size(size);
1089 }
1090
1091 if let Some(val) = c.h2_initial_window_size {
1092 svc = svc.h2_initial_window_size(val);
1093 }
1094
1095 if let Some(val) = c.h2_initial_connection_window_size {
1096 svc = svc.h2_initial_connection_window_size(val);
1097 }
1098
1099 if let Some(handler) = on_connect_fn.clone() {
1100 svc = svc
1101 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1102 };
1103
1104 let fac = factory()
1105 .into_factory()
1106 .map_err(|err| err.into().error_response());
1107
1108 let acceptor_config = match c.tls_handshake_timeout {
1109 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1110 None => TlsAcceptorConfig::default(),
1111 };
1112
1113 svc.finish(map_config(fac, move |_| {
1114 AppConfig::new(true, host.clone(), addr)
1115 }))
1116 .rustls_0_23_with_config(config.clone(), acceptor_config)
1117 })?;
1118
1119 Ok(self)
1120 }
1121
1122 #[cfg(feature = "openssl")]
1129 pub fn listen_openssl(
1130 self,
1131 lst: net::TcpListener,
1132 builder: SslAcceptorBuilder,
1133 ) -> io::Result<Self> {
1134 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1135 }
1136
1137 #[cfg(feature = "openssl")]
1138 fn listen_openssl_inner(
1139 mut self,
1140 lst: net::TcpListener,
1141 acceptor: SslAcceptor,
1142 ) -> io::Result<Self> {
1143 let factory = self.factory.clone();
1144 let cfg = Arc::clone(&self.config);
1145 let addr = lst.local_addr().unwrap();
1146
1147 self.sockets.push(Socket {
1148 addr,
1149 scheme: "https",
1150 });
1151
1152 let on_connect_fn = self.on_connect_fn.clone();
1153 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1154
1155 self.builder =
1156 self.builder
1157 .listen(format!("actix-web-service-{}", addr), lst, move || {
1158 let c = cfg.lock().unwrap();
1159 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1160 let shutdown_signal = graceful_shutdown_signal.clone();
1161
1162 let mut svc = HttpService::build()
1163 .graceful_shutdown_signal(move || {
1164 let signal = shutdown_signal.clone();
1165 async move { signal.notified().await }
1166 })
1167 .keep_alive(c.keep_alive)
1168 .client_request_timeout(c.client_request_timeout)
1169 .client_disconnect_timeout(c.client_disconnect_timeout)
1170 .h1_allow_half_closed(c.h1_allow_half_closed)
1171 .local_addr(addr);
1172
1173 if let Some(enabled) = c.tcp_nodelay {
1174 svc = svc.tcp_nodelay(enabled);
1175 }
1176
1177 if let Some(size) = c.h1_write_buffer_size {
1178 svc = svc.h1_write_buffer_size(size);
1179 }
1180
1181 if let Some(val) = c.h2_initial_window_size {
1182 svc = svc.h2_initial_window_size(val);
1183 }
1184
1185 if let Some(val) = c.h2_initial_connection_window_size {
1186 svc = svc.h2_initial_connection_window_size(val);
1187 }
1188
1189 if let Some(handler) = on_connect_fn.clone() {
1190 svc = svc
1191 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1192 };
1193
1194 let fac = factory()
1195 .into_factory()
1196 .map_err(|err| err.into().error_response());
1197
1198 #[allow(clippy::significant_drop_in_scrutinee)]
1200 let acceptor_config = match c.tls_handshake_timeout {
1201 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1202 None => TlsAcceptorConfig::default(),
1203 };
1204
1205 svc.finish(map_config(fac, move |_| {
1206 AppConfig::new(true, host.clone(), addr)
1207 }))
1208 .openssl_with_config(acceptor.clone(), acceptor_config)
1209 })?;
1210
1211 Ok(self)
1212 }
1213
1214 #[cfg(unix)]
1216 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1217 where
1218 A: AsRef<std::path::Path>,
1219 {
1220 use actix_http::Protocol;
1221 use actix_service::{fn_service, ServiceFactoryExt as _};
1222 use tokio::net::UnixStream;
1223
1224 let cfg = Arc::clone(&self.config);
1225 let factory = self.factory.clone();
1226 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1227 let socket_addr =
1228 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1229
1230 self.sockets.push(Socket {
1231 scheme: "http",
1232 addr: socket_addr,
1233 });
1234
1235 self.builder = self.builder.bind_uds(
1236 format!("actix-web-service-{:?}", uds_path.as_ref()),
1237 uds_path,
1238 move || {
1239 let c = cfg.lock().unwrap();
1240 let config = AppConfig::new(
1241 false,
1242 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1243 socket_addr,
1244 );
1245
1246 let fac = factory()
1247 .into_factory()
1248 .map_err(|err| err.into().error_response());
1249
1250 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1251 let shutdown_signal = graceful_shutdown_signal.clone();
1252 let mut svc = HttpService::build()
1253 .graceful_shutdown_signal(move || {
1254 let signal = shutdown_signal.clone();
1255 async move { signal.notified().await }
1256 })
1257 .keep_alive(c.keep_alive)
1258 .client_request_timeout(c.client_request_timeout)
1259 .client_disconnect_timeout(c.client_disconnect_timeout)
1260 .h1_allow_half_closed(c.h1_allow_half_closed);
1261
1262 if let Some(size) = c.h1_write_buffer_size {
1263 svc = svc.h1_write_buffer_size(size);
1264 }
1265
1266 svc.finish(map_config(fac, move |_| config.clone()))
1267 })
1268 },
1269 )?;
1270
1271 Ok(self)
1272 }
1273
1274 #[cfg(unix)]
1276 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1277 use actix_http::Protocol;
1278 use actix_service::{fn_service, ServiceFactoryExt as _};
1279 use tokio::net::UnixStream;
1280
1281 let cfg = Arc::clone(&self.config);
1282 let factory = self.factory.clone();
1283 let socket_addr =
1284 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1285
1286 self.sockets.push(Socket {
1287 scheme: "http",
1288 addr: socket_addr,
1289 });
1290
1291 let addr = lst.local_addr()?;
1292 let name = format!("actix-web-service-{:?}", addr);
1293 let on_connect_fn = self.on_connect_fn.clone();
1294 let graceful_shutdown_signal = self.graceful_shutdown_signal.clone();
1295
1296 self.builder = self.builder.listen_uds(name, lst, move || {
1297 let c = cfg.lock().unwrap();
1298 let config = AppConfig::new(
1299 false,
1300 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1301 socket_addr,
1302 );
1303
1304 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1305 let shutdown_signal = graceful_shutdown_signal.clone();
1306 let mut svc = HttpService::build()
1307 .graceful_shutdown_signal(move || {
1308 let signal = shutdown_signal.clone();
1309 async move { signal.notified().await }
1310 })
1311 .keep_alive(c.keep_alive)
1312 .client_request_timeout(c.client_request_timeout)
1313 .h1_allow_half_closed(c.h1_allow_half_closed)
1314 .client_disconnect_timeout(c.client_disconnect_timeout);
1315
1316 if let Some(handler) = on_connect_fn.clone() {
1317 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1318 }
1319
1320 if let Some(size) = c.h1_write_buffer_size {
1321 svc = svc.h1_write_buffer_size(size);
1322 }
1323
1324 let fac = factory()
1325 .into_factory()
1326 .map_err(|err| err.into().error_response());
1327
1328 svc.finish(map_config(fac, move |_| config.clone()))
1329 })
1330 })?;
1331 Ok(self)
1332 }
1333}
1334
1335impl<F, I, S, B> HttpServer<F, I, S, B>
1336where
1337 F: Fn() -> I + Send + Clone + 'static,
1338 I: IntoServiceFactory<S, Request>,
1339 S: ServiceFactory<Request, Config = AppConfig>,
1340 S::Error: Into<Error>,
1341 S::InitError: fmt::Debug,
1342 S::Response: Into<Response<B>>,
1343 S::Service: 'static,
1344 B: MessageBody,
1345{
1346 pub fn run(self) -> Server {
1359 self.builder.run()
1360 }
1361}
1362
1363fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1365 let mut err = None;
1366 let mut success = false;
1367 let mut sockets = Vec::new();
1368
1369 for addr in addrs.to_socket_addrs()? {
1370 match create_tcp_listener(addr, backlog) {
1371 Ok(lst) => {
1372 success = true;
1373 sockets.push(lst);
1374 }
1375 Err(error) => err = Some(error),
1376 }
1377 }
1378
1379 if success {
1380 Ok(sockets)
1381 } else if let Some(err) = err.take() {
1382 Err(err)
1383 } else {
1384 Err(io::Error::other("Could not bind to address"))
1385 }
1386}
1387
1388fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1390 use socket2::{Domain, Protocol, Socket, Type};
1391 let domain = Domain::for_address(addr);
1392 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1393 #[cfg(not(windows))]
1394 {
1395 socket.set_reuse_address(true)?;
1396 }
1397 #[cfg(windows)]
1400 if addr.is_ipv6() {
1401 if let Err(err) = socket.set_only_v6(false) {
1402 log::warn!("failed to set IPV6_V6ONLY=false: {err}");
1403 }
1404 }
1405 socket.bind(&addr.into())?;
1406 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1408 socket.listen(backlog)?;
1409 Ok(net::TcpListener::from(socket))
1410}
1411
1412#[cfg(feature = "openssl")]
1414fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1415 builder.set_alpn_select_callback(|_, protocols| {
1416 const H11: &[u8] = b"\x08http/1.1";
1417
1418 #[cfg(feature = "http2")]
1419 {
1420 const H2: &[u8] = b"\x02h2";
1421
1422 if protocols.windows(3).any(|window| window == H2) {
1423 return Ok(b"h2");
1424 }
1425 }
1426
1427 if protocols.windows(9).any(|window| window == H11) {
1428 Ok(b"http/1.1")
1429 } else {
1430 Err(AlpnError::NOACK)
1431 }
1432 });
1433
1434 #[cfg(feature = "http2")]
1435 let protos = b"\x08http/1.1\x02h2";
1436 #[cfg(not(feature = "http2"))]
1437 let protos = b"\x08http/1.1";
1438 builder.set_alpn_protos(protos)?;
1439
1440 Ok(builder.build())
1441}