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