1use std::{
2 any::Any,
3 cmp, fmt,
4 future::Future,
5 io,
6 marker::PhantomData,
7 net,
8 sync::{Arc, Mutex},
9 time::Duration,
10};
11
12#[cfg(feature = "__tls")]
13use actix_http::TlsAcceptorConfig;
14use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
15use actix_server::{Server, ServerBuilder};
16use actix_service::{
17 map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _,
18};
19#[cfg(feature = "openssl")]
20use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder};
21
22use crate::{config::AppConfig, Error};
23
24struct Socket {
25 scheme: &'static str,
26 addr: net::SocketAddr,
27}
28
29struct Config {
30 host: Option<String>,
31 keep_alive: KeepAlive,
32 tcp_nodelay: Option<bool>,
33 client_request_timeout: Duration,
34 client_disconnect_timeout: Duration,
35 h1_allow_half_closed: bool,
36 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 #[allow(clippy::type_complexity)]
91 on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
92 _phantom: PhantomData<(S, B)>,
93}
94
95impl<F, I, S, B> HttpServer<F, I, S, B>
96where
97 F: Fn() -> I + Send + Clone + 'static,
98 I: IntoServiceFactory<S, Request>,
99
100 S: ServiceFactory<Request, Config = AppConfig> + 'static,
101 S::Error: Into<Error> + 'static,
102 S::InitError: fmt::Debug,
103 S::Response: Into<Response<B>> + 'static,
104 <S::Service as Service<Request>>::Future: 'static,
105 S::Service: 'static,
106
107 B: MessageBody + 'static,
108{
109 pub fn new(factory: F) -> Self {
117 HttpServer {
118 factory,
119 config: Arc::new(Mutex::new(Config {
120 host: None,
121 keep_alive: KeepAlive::default(),
122 tcp_nodelay: None,
123 client_request_timeout: Duration::from_secs(5),
124 client_disconnect_timeout: Duration::from_secs(1),
125 h1_allow_half_closed: true,
126 h1_write_buffer_size: None,
127 h2_initial_window_size: None,
128 h2_initial_connection_window_size: None,
129 tls_handshake_timeout: None,
130 })),
131 backlog: 1024,
132 sockets: Vec::new(),
133 builder: ServerBuilder::default(),
134 on_connect_fn: None,
135 _phantom: PhantomData,
136 }
137 }
138
139 pub fn workers(mut self, num: usize) -> Self {
154 self.builder = self.builder.workers(num);
155 self
156 }
157
158 pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
162 self.config.lock().unwrap().keep_alive = val.into();
163 self
164 }
165
166 pub fn tcp_nodelay(self, enabled: bool) -> Self {
171 self.config.lock().unwrap().tcp_nodelay = Some(enabled);
172 self
173 }
174
175 pub fn backlog(mut self, backlog: u32) -> Self {
185 self.backlog = backlog;
186 self.builder = self.builder.backlog(backlog);
187 self
188 }
189
190 pub fn max_connections(mut self, num: usize) -> Self {
197 self.builder = self.builder.max_concurrent_connections(num);
198 self
199 }
200
201 #[allow(unused_variables)]
208 pub fn max_connection_rate(self, num: usize) -> Self {
209 #[cfg(feature = "__tls")]
210 actix_tls::accept::max_concurrent_tls_connect(num);
211 self
212 }
213
214 pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
220 self.builder = self.builder.worker_max_blocking_threads(num);
221 self
222 }
223
224 pub fn client_request_timeout(self, dur: Duration) -> Self {
233 self.config.lock().unwrap().client_request_timeout = dur;
234 self
235 }
236
237 #[doc(hidden)]
238 #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
239 pub fn client_timeout(self, dur: Duration) -> Self {
240 self.client_request_timeout(dur)
241 }
242
243 pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
252 self.config.lock().unwrap().client_disconnect_timeout = dur;
253 self
254 }
255
256 #[cfg(feature = "__tls")]
263 pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
264 self.config
265 .lock()
266 .unwrap()
267 .tls_handshake_timeout
268 .replace(dur);
269
270 self
271 }
272
273 #[doc(hidden)]
274 #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
275 pub fn client_shutdown(self, dur: u64) -> Self {
276 self.client_disconnect_timeout(Duration::from_millis(dur))
277 }
278
279 pub fn h1_allow_half_closed(self, allow: bool) -> Self {
287 self.config.lock().unwrap().h1_allow_half_closed = allow;
288 self
289 }
290
291 pub fn h1_write_buffer_size(self, size: usize) -> Self {
301 assert!(
302 size > 0,
303 "HTTP/1 write buffer size must be greater than zero"
304 );
305
306 self.config.lock().unwrap().h1_write_buffer_size = Some(size);
307 self
308 }
309
310 #[cfg(feature = "http2")]
317 pub fn h2_initial_window_size(self, size: u32) -> Self {
318 self.config.lock().unwrap().h2_initial_window_size = Some(size);
319 self
320 }
321
322 #[cfg(feature = "http2")]
329 pub fn h2_initial_connection_window_size(self, size: u32) -> Self {
330 self.config
331 .lock()
332 .unwrap()
333 .h2_initial_connection_window_size = Some(size);
334 self
335 }
336
337 pub fn on_connect<CB>(mut self, f: CB) -> HttpServer<F, I, S, B>
356 where
357 CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
358 {
359 self.on_connect_fn = Some(Arc::new(f));
360 self
361 }
362
363 pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
370 self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
371 self
372 }
373
374 pub fn system_exit(mut self) -> Self {
378 self.builder = self.builder.system_exit();
379 self
380 }
381
382 pub fn disable_signals(mut self) -> Self {
384 self.builder = self.builder.disable_signals();
385 self
386 }
387
388 pub fn shutdown_signal<Fut>(mut self, shutdown_signal: Fut) -> Self
412 where
413 Fut: Future<Output = ()> + Send + 'static,
414 {
415 self.builder = self.builder.shutdown_signal(shutdown_signal);
416 self
417 }
418
419 pub fn shutdown_timeout(mut self, sec: u64) -> Self {
426 self.builder = self.builder.shutdown_timeout(sec);
427 self
428 }
429
430 pub fn addrs(&self) -> Vec<net::SocketAddr> {
432 self.sockets.iter().map(|s| s.addr).collect()
433 }
434
435 pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
441 self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
442 }
443
444 pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
499 let sockets = bind_addrs(addrs, self.backlog)?;
500
501 for lst in sockets {
502 self = self.listen(lst)?;
503 }
504
505 Ok(self)
506 }
507
508 #[cfg(feature = "http2")]
513 pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
514 let sockets = bind_addrs(addrs, self.backlog)?;
515
516 for lst in sockets {
517 self = self.listen_auto_h2c(lst)?;
518 }
519
520 Ok(self)
521 }
522
523 #[cfg(feature = "rustls-0_20")]
530 pub fn bind_rustls<A: net::ToSocketAddrs>(
531 mut self,
532 addrs: A,
533 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
534 ) -> io::Result<Self> {
535 let sockets = bind_addrs(addrs, self.backlog)?;
536 for lst in sockets {
537 self = self.listen_rustls_0_20_inner(lst, config.clone())?;
538 }
539 Ok(self)
540 }
541
542 #[cfg(feature = "rustls-0_21")]
549 pub fn bind_rustls_021<A: net::ToSocketAddrs>(
550 mut self,
551 addrs: A,
552 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
553 ) -> io::Result<Self> {
554 let sockets = bind_addrs(addrs, self.backlog)?;
555 for lst in sockets {
556 self = self.listen_rustls_0_21_inner(lst, config.clone())?;
557 }
558 Ok(self)
559 }
560
561 #[cfg(feature = "rustls-0_22")]
568 pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
569 mut self,
570 addrs: A,
571 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
572 ) -> io::Result<Self> {
573 let sockets = bind_addrs(addrs, self.backlog)?;
574 for lst in sockets {
575 self = self.listen_rustls_0_22_inner(lst, config.clone())?;
576 }
577 Ok(self)
578 }
579
580 #[cfg(feature = "rustls-0_23")]
587 pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
588 mut self,
589 addrs: A,
590 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
591 ) -> io::Result<Self> {
592 let sockets = bind_addrs(addrs, self.backlog)?;
593 for lst in sockets {
594 self = self.listen_rustls_0_23_inner(lst, config.clone())?;
595 }
596 Ok(self)
597 }
598
599 #[cfg(feature = "openssl")]
606 pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
607 where
608 A: net::ToSocketAddrs,
609 {
610 let sockets = bind_addrs(addrs, self.backlog)?;
611 let acceptor = openssl_acceptor(builder)?;
612
613 for lst in sockets {
614 self = self.listen_openssl_inner(lst, acceptor.clone())?;
615 }
616
617 Ok(self)
618 }
619
620 pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
625 let cfg = Arc::clone(&self.config);
626 let factory = self.factory.clone();
627 let addr = lst.local_addr().unwrap();
628
629 self.sockets.push(Socket {
630 addr,
631 scheme: "http",
632 });
633
634 let on_connect_fn = self.on_connect_fn.clone();
635
636 self.builder =
637 self.builder
638 .listen(format!("actix-web-service-{}", addr), lst, move || {
639 let cfg = cfg.lock().unwrap();
640 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
641
642 let mut svc = HttpService::build()
643 .keep_alive(cfg.keep_alive)
644 .client_request_timeout(cfg.client_request_timeout)
645 .client_disconnect_timeout(cfg.client_disconnect_timeout)
646 .h1_allow_half_closed(cfg.h1_allow_half_closed)
647 .local_addr(addr);
648
649 if let Some(enabled) = cfg.tcp_nodelay {
650 svc = svc.tcp_nodelay(enabled);
651 }
652
653 if let Some(size) = cfg.h1_write_buffer_size {
654 svc = svc.h1_write_buffer_size(size);
655 }
656
657 if let Some(val) = cfg.h2_initial_window_size {
658 svc = svc.h2_initial_window_size(val);
659 }
660
661 if let Some(val) = cfg.h2_initial_connection_window_size {
662 svc = svc.h2_initial_connection_window_size(val);
663 }
664
665 if let Some(handler) = on_connect_fn.clone() {
666 svc =
667 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
668 };
669
670 let fac = factory()
671 .into_factory()
672 .map_err(|err| err.into().error_response());
673
674 svc.finish(map_config(fac, move |_| {
675 AppConfig::new(false, host.clone(), addr)
676 }))
677 .tcp()
678 })?;
679
680 Ok(self)
681 }
682
683 #[cfg(feature = "http2")]
685 pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
686 let cfg = Arc::clone(&self.config);
687 let factory = self.factory.clone();
688 let addr = lst.local_addr().unwrap();
689
690 self.sockets.push(Socket {
691 addr,
692 scheme: "http",
693 });
694
695 let on_connect_fn = self.on_connect_fn.clone();
696
697 self.builder =
698 self.builder
699 .listen(format!("actix-web-service-{}", addr), lst, move || {
700 let cfg = cfg.lock().unwrap();
701 let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
702
703 let mut svc = HttpService::build()
704 .keep_alive(cfg.keep_alive)
705 .client_request_timeout(cfg.client_request_timeout)
706 .client_disconnect_timeout(cfg.client_disconnect_timeout)
707 .h1_allow_half_closed(cfg.h1_allow_half_closed)
708 .local_addr(addr);
709
710 if let Some(enabled) = cfg.tcp_nodelay {
711 svc = svc.tcp_nodelay(enabled);
712 }
713
714 if let Some(size) = cfg.h1_write_buffer_size {
715 svc = svc.h1_write_buffer_size(size);
716 }
717
718 if let Some(val) = cfg.h2_initial_window_size {
719 svc = svc.h2_initial_window_size(val);
720 }
721
722 if let Some(val) = cfg.h2_initial_connection_window_size {
723 svc = svc.h2_initial_connection_window_size(val);
724 }
725
726 if let Some(handler) = on_connect_fn.clone() {
727 svc =
728 svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
729 };
730
731 let fac = factory()
732 .into_factory()
733 .map_err(|err| err.into().error_response());
734
735 svc.finish(map_config(fac, move |_| {
736 AppConfig::new(false, host.clone(), addr)
737 }))
738 .tcp_auto_h2c()
739 })?;
740
741 Ok(self)
742 }
743
744 #[cfg(feature = "rustls-0_20")]
751 pub fn listen_rustls(
752 self,
753 lst: net::TcpListener,
754 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
755 ) -> io::Result<Self> {
756 self.listen_rustls_0_20_inner(lst, config)
757 }
758
759 #[cfg(feature = "rustls-0_21")]
766 pub fn listen_rustls_0_21(
767 self,
768 lst: net::TcpListener,
769 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
770 ) -> io::Result<Self> {
771 self.listen_rustls_0_21_inner(lst, config)
772 }
773
774 #[cfg(feature = "rustls-0_20")]
775 fn listen_rustls_0_20_inner(
776 mut self,
777 lst: net::TcpListener,
778 config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
779 ) -> io::Result<Self> {
780 let factory = self.factory.clone();
781 let cfg = Arc::clone(&self.config);
782 let addr = lst.local_addr().unwrap();
783 self.sockets.push(Socket {
784 addr,
785 scheme: "https",
786 });
787
788 let on_connect_fn = self.on_connect_fn.clone();
789
790 self.builder =
791 self.builder
792 .listen(format!("actix-web-service-{}", addr), lst, move || {
793 let c = cfg.lock().unwrap();
794 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
795
796 let mut svc = HttpService::build()
797 .keep_alive(c.keep_alive)
798 .client_request_timeout(c.client_request_timeout)
799 .h1_allow_half_closed(c.h1_allow_half_closed)
800 .client_disconnect_timeout(c.client_disconnect_timeout);
801
802 if let Some(enabled) = c.tcp_nodelay {
803 svc = svc.tcp_nodelay(enabled);
804 }
805
806 if let Some(size) = c.h1_write_buffer_size {
807 svc = svc.h1_write_buffer_size(size);
808 }
809
810 if let Some(val) = c.h2_initial_window_size {
811 svc = svc.h2_initial_window_size(val);
812 }
813
814 if let Some(val) = c.h2_initial_connection_window_size {
815 svc = svc.h2_initial_connection_window_size(val);
816 }
817
818 if let Some(handler) = on_connect_fn.clone() {
819 svc = svc
820 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
821 };
822
823 let fac = factory()
824 .into_factory()
825 .map_err(|err| err.into().error_response());
826
827 let acceptor_config = match c.tls_handshake_timeout {
828 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
829 None => TlsAcceptorConfig::default(),
830 };
831
832 svc.finish(map_config(fac, move |_| {
833 AppConfig::new(true, host.clone(), addr)
834 }))
835 .rustls_with_config(config.clone(), acceptor_config)
836 })?;
837
838 Ok(self)
839 }
840
841 #[cfg(feature = "rustls-0_21")]
842 fn listen_rustls_0_21_inner(
843 mut self,
844 lst: net::TcpListener,
845 config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
846 ) -> io::Result<Self> {
847 let factory = self.factory.clone();
848 let cfg = Arc::clone(&self.config);
849 let addr = lst.local_addr().unwrap();
850 self.sockets.push(Socket {
851 addr,
852 scheme: "https",
853 });
854
855 let on_connect_fn = self.on_connect_fn.clone();
856
857 self.builder =
858 self.builder
859 .listen(format!("actix-web-service-{}", addr), lst, move || {
860 let c = cfg.lock().unwrap();
861 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
862
863 let mut svc = HttpService::build()
864 .keep_alive(c.keep_alive)
865 .client_request_timeout(c.client_request_timeout)
866 .h1_allow_half_closed(c.h1_allow_half_closed)
867 .client_disconnect_timeout(c.client_disconnect_timeout);
868
869 if let Some(enabled) = c.tcp_nodelay {
870 svc = svc.tcp_nodelay(enabled);
871 }
872
873 if let Some(size) = c.h1_write_buffer_size {
874 svc = svc.h1_write_buffer_size(size);
875 }
876
877 if let Some(val) = c.h2_initial_window_size {
878 svc = svc.h2_initial_window_size(val);
879 }
880
881 if let Some(val) = c.h2_initial_connection_window_size {
882 svc = svc.h2_initial_connection_window_size(val);
883 }
884
885 if let Some(handler) = on_connect_fn.clone() {
886 svc = svc
887 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
888 };
889
890 let fac = factory()
891 .into_factory()
892 .map_err(|err| err.into().error_response());
893
894 let acceptor_config = match c.tls_handshake_timeout {
895 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
896 None => TlsAcceptorConfig::default(),
897 };
898
899 svc.finish(map_config(fac, move |_| {
900 AppConfig::new(true, host.clone(), addr)
901 }))
902 .rustls_021_with_config(config.clone(), acceptor_config)
903 })?;
904
905 Ok(self)
906 }
907
908 #[cfg(feature = "rustls-0_22")]
915 pub fn listen_rustls_0_22(
916 self,
917 lst: net::TcpListener,
918 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
919 ) -> io::Result<Self> {
920 self.listen_rustls_0_22_inner(lst, config)
921 }
922
923 #[cfg(feature = "rustls-0_22")]
924 fn listen_rustls_0_22_inner(
925 mut self,
926 lst: net::TcpListener,
927 config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
928 ) -> io::Result<Self> {
929 let factory = self.factory.clone();
930 let cfg = Arc::clone(&self.config);
931 let addr = lst.local_addr().unwrap();
932 self.sockets.push(Socket {
933 addr,
934 scheme: "https",
935 });
936
937 let on_connect_fn = self.on_connect_fn.clone();
938
939 self.builder =
940 self.builder
941 .listen(format!("actix-web-service-{}", addr), lst, move || {
942 let c = cfg.lock().unwrap();
943 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
944
945 let mut svc = HttpService::build()
946 .keep_alive(c.keep_alive)
947 .client_request_timeout(c.client_request_timeout)
948 .h1_allow_half_closed(c.h1_allow_half_closed)
949 .client_disconnect_timeout(c.client_disconnect_timeout);
950
951 if let Some(enabled) = c.tcp_nodelay {
952 svc = svc.tcp_nodelay(enabled);
953 }
954
955 if let Some(size) = c.h1_write_buffer_size {
956 svc = svc.h1_write_buffer_size(size);
957 }
958
959 if let Some(val) = c.h2_initial_window_size {
960 svc = svc.h2_initial_window_size(val);
961 }
962
963 if let Some(val) = c.h2_initial_connection_window_size {
964 svc = svc.h2_initial_connection_window_size(val);
965 }
966
967 if let Some(handler) = on_connect_fn.clone() {
968 svc = svc
969 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
970 };
971
972 let fac = factory()
973 .into_factory()
974 .map_err(|err| err.into().error_response());
975
976 let acceptor_config = match c.tls_handshake_timeout {
977 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
978 None => TlsAcceptorConfig::default(),
979 };
980
981 svc.finish(map_config(fac, move |_| {
982 AppConfig::new(true, host.clone(), addr)
983 }))
984 .rustls_0_22_with_config(config.clone(), acceptor_config)
985 })?;
986
987 Ok(self)
988 }
989
990 #[cfg(feature = "rustls-0_23")]
997 pub fn listen_rustls_0_23(
998 self,
999 lst: net::TcpListener,
1000 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1001 ) -> io::Result<Self> {
1002 self.listen_rustls_0_23_inner(lst, config)
1003 }
1004
1005 #[cfg(feature = "rustls-0_23")]
1006 fn listen_rustls_0_23_inner(
1007 mut self,
1008 lst: net::TcpListener,
1009 config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
1010 ) -> io::Result<Self> {
1011 let factory = self.factory.clone();
1012 let cfg = Arc::clone(&self.config);
1013 let addr = lst.local_addr().unwrap();
1014 self.sockets.push(Socket {
1015 addr,
1016 scheme: "https",
1017 });
1018
1019 let on_connect_fn = self.on_connect_fn.clone();
1020
1021 self.builder =
1022 self.builder
1023 .listen(format!("actix-web-service-{}", addr), lst, move || {
1024 let c = cfg.lock().unwrap();
1025 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1026
1027 let mut svc = HttpService::build()
1028 .keep_alive(c.keep_alive)
1029 .client_request_timeout(c.client_request_timeout)
1030 .h1_allow_half_closed(c.h1_allow_half_closed)
1031 .client_disconnect_timeout(c.client_disconnect_timeout);
1032
1033 if let Some(enabled) = c.tcp_nodelay {
1034 svc = svc.tcp_nodelay(enabled);
1035 }
1036
1037 if let Some(size) = c.h1_write_buffer_size {
1038 svc = svc.h1_write_buffer_size(size);
1039 }
1040
1041 if let Some(val) = c.h2_initial_window_size {
1042 svc = svc.h2_initial_window_size(val);
1043 }
1044
1045 if let Some(val) = c.h2_initial_connection_window_size {
1046 svc = svc.h2_initial_connection_window_size(val);
1047 }
1048
1049 if let Some(handler) = on_connect_fn.clone() {
1050 svc = svc
1051 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1052 };
1053
1054 let fac = factory()
1055 .into_factory()
1056 .map_err(|err| err.into().error_response());
1057
1058 let acceptor_config = match c.tls_handshake_timeout {
1059 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1060 None => TlsAcceptorConfig::default(),
1061 };
1062
1063 svc.finish(map_config(fac, move |_| {
1064 AppConfig::new(true, host.clone(), addr)
1065 }))
1066 .rustls_0_23_with_config(config.clone(), acceptor_config)
1067 })?;
1068
1069 Ok(self)
1070 }
1071
1072 #[cfg(feature = "openssl")]
1078 pub fn listen_openssl(
1079 self,
1080 lst: net::TcpListener,
1081 builder: SslAcceptorBuilder,
1082 ) -> io::Result<Self> {
1083 self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
1084 }
1085
1086 #[cfg(feature = "openssl")]
1087 fn listen_openssl_inner(
1088 mut self,
1089 lst: net::TcpListener,
1090 acceptor: SslAcceptor,
1091 ) -> io::Result<Self> {
1092 let factory = self.factory.clone();
1093 let cfg = Arc::clone(&self.config);
1094 let addr = lst.local_addr().unwrap();
1095
1096 self.sockets.push(Socket {
1097 addr,
1098 scheme: "https",
1099 });
1100
1101 let on_connect_fn = self.on_connect_fn.clone();
1102
1103 self.builder =
1104 self.builder
1105 .listen(format!("actix-web-service-{}", addr), lst, move || {
1106 let c = cfg.lock().unwrap();
1107 let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
1108
1109 let mut svc = HttpService::build()
1110 .keep_alive(c.keep_alive)
1111 .client_request_timeout(c.client_request_timeout)
1112 .client_disconnect_timeout(c.client_disconnect_timeout)
1113 .h1_allow_half_closed(c.h1_allow_half_closed)
1114 .local_addr(addr);
1115
1116 if let Some(enabled) = c.tcp_nodelay {
1117 svc = svc.tcp_nodelay(enabled);
1118 }
1119
1120 if let Some(size) = c.h1_write_buffer_size {
1121 svc = svc.h1_write_buffer_size(size);
1122 }
1123
1124 if let Some(val) = c.h2_initial_window_size {
1125 svc = svc.h2_initial_window_size(val);
1126 }
1127
1128 if let Some(val) = c.h2_initial_connection_window_size {
1129 svc = svc.h2_initial_connection_window_size(val);
1130 }
1131
1132 if let Some(handler) = on_connect_fn.clone() {
1133 svc = svc
1134 .on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1135 };
1136
1137 let fac = factory()
1138 .into_factory()
1139 .map_err(|err| err.into().error_response());
1140
1141 #[allow(clippy::significant_drop_in_scrutinee)]
1143 let acceptor_config = match c.tls_handshake_timeout {
1144 Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
1145 None => TlsAcceptorConfig::default(),
1146 };
1147
1148 svc.finish(map_config(fac, move |_| {
1149 AppConfig::new(true, host.clone(), addr)
1150 }))
1151 .openssl_with_config(acceptor.clone(), acceptor_config)
1152 })?;
1153
1154 Ok(self)
1155 }
1156
1157 #[cfg(unix)]
1159 pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
1160 where
1161 A: AsRef<std::path::Path>,
1162 {
1163 use actix_http::Protocol;
1164 use actix_rt::net::UnixStream;
1165 use actix_service::{fn_service, ServiceFactoryExt as _};
1166
1167 let cfg = Arc::clone(&self.config);
1168 let factory = self.factory.clone();
1169 let socket_addr =
1170 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1171
1172 self.sockets.push(Socket {
1173 scheme: "http",
1174 addr: socket_addr,
1175 });
1176
1177 self.builder = self.builder.bind_uds(
1178 format!("actix-web-service-{:?}", uds_path.as_ref()),
1179 uds_path,
1180 move || {
1181 let c = cfg.lock().unwrap();
1182 let config = AppConfig::new(
1183 false,
1184 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1185 socket_addr,
1186 );
1187
1188 let fac = factory()
1189 .into_factory()
1190 .map_err(|err| err.into().error_response());
1191
1192 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1193 let mut svc = HttpService::build()
1194 .keep_alive(c.keep_alive)
1195 .client_request_timeout(c.client_request_timeout)
1196 .client_disconnect_timeout(c.client_disconnect_timeout)
1197 .h1_allow_half_closed(c.h1_allow_half_closed);
1198
1199 if let Some(size) = c.h1_write_buffer_size {
1200 svc = svc.h1_write_buffer_size(size);
1201 }
1202
1203 svc.finish(map_config(fac, move |_| config.clone()))
1204 })
1205 },
1206 )?;
1207
1208 Ok(self)
1209 }
1210
1211 #[cfg(unix)]
1213 pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
1214 use actix_http::Protocol;
1215 use actix_rt::net::UnixStream;
1216 use actix_service::{fn_service, ServiceFactoryExt as _};
1217
1218 let cfg = Arc::clone(&self.config);
1219 let factory = self.factory.clone();
1220 let socket_addr =
1221 net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
1222
1223 self.sockets.push(Socket {
1224 scheme: "http",
1225 addr: socket_addr,
1226 });
1227
1228 let addr = lst.local_addr()?;
1229 let name = format!("actix-web-service-{:?}", addr);
1230 let on_connect_fn = self.on_connect_fn.clone();
1231
1232 self.builder = self.builder.listen_uds(name, lst, move || {
1233 let c = cfg.lock().unwrap();
1234 let config = AppConfig::new(
1235 false,
1236 c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1237 socket_addr,
1238 );
1239
1240 fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1241 let mut svc = HttpService::build()
1242 .keep_alive(c.keep_alive)
1243 .client_request_timeout(c.client_request_timeout)
1244 .h1_allow_half_closed(c.h1_allow_half_closed)
1245 .client_disconnect_timeout(c.client_disconnect_timeout);
1246
1247 if let Some(handler) = on_connect_fn.clone() {
1248 svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1249 }
1250
1251 if let Some(size) = c.h1_write_buffer_size {
1252 svc = svc.h1_write_buffer_size(size);
1253 }
1254
1255 let fac = factory()
1256 .into_factory()
1257 .map_err(|err| err.into().error_response());
1258
1259 svc.finish(map_config(fac, move |_| config.clone()))
1260 })
1261 })?;
1262 Ok(self)
1263 }
1264}
1265
1266impl<F, I, S, B> HttpServer<F, I, S, B>
1267where
1268 F: Fn() -> I + Send + Clone + 'static,
1269 I: IntoServiceFactory<S, Request>,
1270 S: ServiceFactory<Request, Config = AppConfig>,
1271 S::Error: Into<Error>,
1272 S::InitError: fmt::Debug,
1273 S::Response: Into<Response<B>>,
1274 S::Service: 'static,
1275 B: MessageBody,
1276{
1277 pub fn run(self) -> Server {
1290 self.builder.run()
1291 }
1292}
1293
1294fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1296 let mut err = None;
1297 let mut success = false;
1298 let mut sockets = Vec::new();
1299
1300 for addr in addrs.to_socket_addrs()? {
1301 match create_tcp_listener(addr, backlog) {
1302 Ok(lst) => {
1303 success = true;
1304 sockets.push(lst);
1305 }
1306 Err(error) => err = Some(error),
1307 }
1308 }
1309
1310 if success {
1311 Ok(sockets)
1312 } else if let Some(err) = err.take() {
1313 Err(err)
1314 } else {
1315 Err(io::Error::other("Could not bind to address"))
1316 }
1317}
1318
1319fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1321 use socket2::{Domain, Protocol, Socket, Type};
1322 let domain = Domain::for_address(addr);
1323 let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1324 #[cfg(not(windows))]
1325 {
1326 socket.set_reuse_address(true)?;
1327 }
1328 #[cfg(windows)]
1331 if addr.is_ipv6() {
1332 if let Err(err) = socket.set_only_v6(false) {
1333 log::warn!("failed to set IPV6_V6ONLY=false: {err}");
1334 }
1335 }
1336 socket.bind(&addr.into())?;
1337 let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1339 socket.listen(backlog)?;
1340 Ok(net::TcpListener::from(socket))
1341}
1342
1343#[cfg(feature = "openssl")]
1345fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1346 builder.set_alpn_select_callback(|_, protocols| {
1347 const H2: &[u8] = b"\x02h2";
1348 const H11: &[u8] = b"\x08http/1.1";
1349
1350 if protocols.windows(3).any(|window| window == H2) {
1351 Ok(b"h2")
1352 } else if protocols.windows(9).any(|window| window == H11) {
1353 Ok(b"http/1.1")
1354 } else {
1355 Err(AlpnError::NOACK)
1356 }
1357 });
1358
1359 builder.set_alpn_protos(b"\x08http/1.1\x02h2")?;
1360
1361 Ok(builder.build())
1362}