actix_web/
server.rs

1use std::{
2    any::Any,
3    cmp, fmt, io,
4    marker::PhantomData,
5    net,
6    sync::{Arc, Mutex},
7    time::Duration,
8};
9
10#[cfg(feature = "__tls")]
11use actix_http::TlsAcceptorConfig;
12use actix_http::{body::MessageBody, Extensions, HttpService, KeepAlive, Request, Response};
13use actix_server::{Server, ServerBuilder};
14use actix_service::{
15    map_config, IntoServiceFactory, Service, ServiceFactory, ServiceFactoryExt as _,
16};
17#[cfg(feature = "openssl")]
18use actix_tls::accept::openssl::reexports::{AlpnError, SslAcceptor, SslAcceptorBuilder};
19
20use crate::{config::AppConfig, Error};
21
22struct Socket {
23    scheme: &'static str,
24    addr: net::SocketAddr,
25}
26
27struct Config {
28    host: Option<String>,
29    keep_alive: KeepAlive,
30    client_request_timeout: Duration,
31    client_disconnect_timeout: Duration,
32    #[allow(dead_code)] // only dead when no TLS features are enabled
33    tls_handshake_timeout: Option<Duration>,
34}
35
36/// An HTTP Server.
37///
38/// Create new HTTP server with application factory.
39///
40/// # Automatic HTTP Version Selection
41///
42/// There are two ways to select the HTTP version of an incoming connection:
43///
44/// - One is to rely on the ALPN information that is provided when using a TLS (HTTPS); both
45///   versions are supported automatically when using either of the `.bind_rustls()` or
46///   `.bind_openssl()` methods.
47/// - The other is to read the first few bytes of the TCP stream. This is the only viable approach
48///   for supporting H2C, which allows the HTTP/2 protocol to work over plaintext connections. Use
49///   the `.bind_auto_h2c()` method to enable this behavior.
50///
51/// # Examples
52///
53/// ```no_run
54/// use actix_web::{web, App, HttpResponse, HttpServer};
55///
56/// #[actix_web::main]
57/// async fn main() -> std::io::Result<()> {
58///     HttpServer::new(|| {
59///         App::new()
60///             .service(web::resource("/").to(|| async { "hello world" }))
61///     })
62///     .bind(("127.0.0.1", 8080))?
63///     .run()
64///     .await
65/// }
66/// ```
67pub struct HttpServer<F, I, S, B>
68where
69    F: Fn() -> I + Send + Clone + 'static,
70    I: IntoServiceFactory<S, Request>,
71    S: ServiceFactory<Request, Config = AppConfig>,
72    S::Error: Into<Error>,
73    S::InitError: fmt::Debug,
74    S::Response: Into<Response<B>>,
75    B: MessageBody,
76{
77    pub(super) factory: F,
78    config: Arc<Mutex<Config>>,
79    backlog: u32,
80    sockets: Vec<Socket>,
81    builder: ServerBuilder,
82    #[allow(clippy::type_complexity)]
83    on_connect_fn: Option<Arc<dyn Fn(&dyn Any, &mut Extensions) + Send + Sync>>,
84    _phantom: PhantomData<(S, B)>,
85}
86
87impl<F, I, S, B> HttpServer<F, I, S, B>
88where
89    F: Fn() -> I + Send + Clone + 'static,
90    I: IntoServiceFactory<S, Request>,
91
92    S: ServiceFactory<Request, Config = AppConfig> + 'static,
93    S::Error: Into<Error> + 'static,
94    S::InitError: fmt::Debug,
95    S::Response: Into<Response<B>> + 'static,
96    <S::Service as Service<Request>>::Future: 'static,
97    S::Service: 'static,
98
99    B: MessageBody + 'static,
100{
101    /// Create new HTTP server with application factory
102    ///
103    /// # Worker Count
104    ///
105    /// The `factory` will be instantiated multiple times in most configurations. See
106    /// [`bind()`](Self::bind()) docs for more on how worker count and bind address resolution
107    /// causes multiple server factory instantiations.
108    pub fn new(factory: F) -> Self {
109        HttpServer {
110            factory,
111            config: Arc::new(Mutex::new(Config {
112                host: None,
113                keep_alive: KeepAlive::default(),
114                client_request_timeout: Duration::from_secs(5),
115                client_disconnect_timeout: Duration::from_secs(1),
116                tls_handshake_timeout: None,
117            })),
118            backlog: 1024,
119            sockets: Vec::new(),
120            builder: ServerBuilder::default(),
121            on_connect_fn: None,
122            _phantom: PhantomData,
123        }
124    }
125
126    /// Sets number of workers to start (per bind address).
127    ///
128    /// The default worker count is the determined by [`std::thread::available_parallelism()`]. See
129    /// its documentation to determine what behavior you should expect when server is run.
130    ///
131    /// Note that the server factory passed to [`new`](Self::new()) will be instantiated **at least
132    /// once per worker**. See [`bind()`](Self::bind()) docs for more on how worker count and bind
133    /// address resolution causes multiple server factory instantiations.
134    ///
135    /// `num` must be greater than 0.
136    ///
137    /// # Panics
138    ///
139    /// Panics if `num` is 0.
140    pub fn workers(mut self, num: usize) -> Self {
141        self.builder = self.builder.workers(num);
142        self
143    }
144
145    /// Sets server keep-alive preference.
146    ///
147    /// By default keep-alive is set to 5 seconds.
148    pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
149        self.config.lock().unwrap().keep_alive = val.into();
150        self
151    }
152
153    /// Sets the maximum number of pending connections.
154    ///
155    /// This refers to the number of clients that can be waiting to be served. Exceeding this number
156    /// results in the client getting an error when attempting to connect. It should only affect
157    /// servers under significant load.
158    ///
159    /// Generally set in the 64–2048 range. Default value is 2048.
160    ///
161    /// This method will have no effect if called after a `bind()`.
162    pub fn backlog(mut self, backlog: u32) -> Self {
163        self.backlog = backlog;
164        self.builder = self.builder.backlog(backlog);
165        self
166    }
167
168    /// Sets the per-worker maximum number of concurrent connections.
169    ///
170    /// All socket listeners will stop accepting connections when this limit is reached for
171    /// each worker.
172    ///
173    /// By default max connections is set to a 25k.
174    pub fn max_connections(mut self, num: usize) -> Self {
175        self.builder = self.builder.max_concurrent_connections(num);
176        self
177    }
178
179    /// Sets the per-worker maximum concurrent TLS connection limit.
180    ///
181    /// All listeners will stop accepting connections when this limit is reached. It can be used to
182    /// limit the global TLS CPU usage.
183    ///
184    /// By default max connections is set to a 256.
185    #[allow(unused_variables)]
186    pub fn max_connection_rate(self, num: usize) -> Self {
187        #[cfg(feature = "__tls")]
188        actix_tls::accept::max_concurrent_tls_connect(num);
189        self
190    }
191
192    /// Sets max number of threads for each worker's blocking task thread pool.
193    ///
194    /// One thread pool is set up **per worker**; not shared across workers.
195    ///
196    /// By default, set to 512 divided by [available parallelism](std::thread::available_parallelism()).
197    pub fn worker_max_blocking_threads(mut self, num: usize) -> Self {
198        self.builder = self.builder.worker_max_blocking_threads(num);
199        self
200    }
201
202    /// Sets server client timeout for first request.
203    ///
204    /// Defines a timeout for reading client request head. If a client does not transmit the entire
205    /// set headers within this time, the request is terminated with a 408 (Request Timeout) error.
206    ///
207    /// To disable timeout set value to 0.
208    ///
209    /// By default client timeout is set to 5000 milliseconds.
210    pub fn client_request_timeout(self, dur: Duration) -> Self {
211        self.config.lock().unwrap().client_request_timeout = dur;
212        self
213    }
214
215    #[doc(hidden)]
216    #[deprecated(since = "4.0.0", note = "Renamed to `client_request_timeout`.")]
217    pub fn client_timeout(self, dur: Duration) -> Self {
218        self.client_request_timeout(dur)
219    }
220
221    /// Sets server connection shutdown timeout.
222    ///
223    /// Defines a timeout for connection shutdown. If a shutdown procedure does not complete within
224    /// this time, the request is dropped.
225    ///
226    /// To disable timeout set value to 0.
227    ///
228    /// By default client timeout is set to 5000 milliseconds.
229    pub fn client_disconnect_timeout(self, dur: Duration) -> Self {
230        self.config.lock().unwrap().client_disconnect_timeout = dur;
231        self
232    }
233
234    /// Sets TLS handshake timeout.
235    ///
236    /// Defines a timeout for TLS handshake. If the TLS handshake does not complete within this
237    /// time, the connection is closed.
238    ///
239    /// By default, the handshake timeout is 3 seconds.
240    #[cfg(feature = "__tls")]
241    pub fn tls_handshake_timeout(self, dur: Duration) -> Self {
242        self.config
243            .lock()
244            .unwrap()
245            .tls_handshake_timeout
246            .replace(dur);
247
248        self
249    }
250
251    #[doc(hidden)]
252    #[deprecated(since = "4.0.0", note = "Renamed to `client_disconnect_timeout`.")]
253    pub fn client_shutdown(self, dur: u64) -> Self {
254        self.client_disconnect_timeout(Duration::from_millis(dur))
255    }
256
257    /// Sets function that will be called once before each connection is handled.
258    ///
259    /// It will receive a `&std::any::Any`, which contains underlying connection type and an
260    /// [Extensions] container so that connection data can be accessed in middleware and handlers.
261    ///
262    /// # Connection Types
263    /// - `actix_tls::accept::openssl::TlsStream<actix_web::rt::net::TcpStream>` when using OpenSSL.
264    /// - `actix_tls::accept::rustls_0_20::TlsStream<actix_web::rt::net::TcpStream>` when using
265    ///   Rustls v0.20.
266    /// - `actix_tls::accept::rustls_0_21::TlsStream<actix_web::rt::net::TcpStream>` when using
267    ///   Rustls v0.21.
268    /// - `actix_tls::accept::rustls_0_22::TlsStream<actix_web::rt::net::TcpStream>` when using
269    ///   Rustls v0.22.
270    /// - `actix_tls::accept::rustls_0_23::TlsStream<actix_web::rt::net::TcpStream>` when using
271    ///   Rustls v0.23.
272    /// - `actix_web::rt::net::TcpStream` when no encryption is used.
273    ///
274    /// See the `on_connect` example for additional details.
275    pub fn on_connect<CB>(self, f: CB) -> HttpServer<F, I, S, B>
276    where
277        CB: Fn(&dyn Any, &mut Extensions) + Send + Sync + 'static,
278    {
279        HttpServer {
280            factory: self.factory,
281            config: self.config,
282            backlog: self.backlog,
283            sockets: self.sockets,
284            builder: self.builder,
285            on_connect_fn: Some(Arc::new(f)),
286            _phantom: PhantomData,
287        }
288    }
289
290    /// Sets server host name.
291    ///
292    /// Host name is used by application router as a hostname for url generation. Check
293    /// [`ConnectionInfo`](crate::dev::ConnectionInfo::host()) docs for more info.
294    ///
295    /// By default, hostname is set to "localhost".
296    pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
297        self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
298        self
299    }
300
301    /// Flags the `System` to exit after server shutdown.
302    ///
303    /// Does nothing when running under `#[tokio::main]` runtime.
304    pub fn system_exit(mut self) -> Self {
305        self.builder = self.builder.system_exit();
306        self
307    }
308
309    /// Disables signal handling.
310    pub fn disable_signals(mut self) -> Self {
311        self.builder = self.builder.disable_signals();
312        self
313    }
314
315    /// Sets timeout for graceful worker shutdown of workers.
316    ///
317    /// After receiving a stop signal, workers have this much time to finish serving requests.
318    /// Workers still alive after the timeout are force dropped.
319    ///
320    /// By default shutdown timeout sets to 30 seconds.
321    pub fn shutdown_timeout(mut self, sec: u64) -> Self {
322        self.builder = self.builder.shutdown_timeout(sec);
323        self
324    }
325
326    /// Returns addresses of bound sockets.
327    pub fn addrs(&self) -> Vec<net::SocketAddr> {
328        self.sockets.iter().map(|s| s.addr).collect()
329    }
330
331    /// Returns addresses of bound sockets and the scheme for it.
332    ///
333    /// This is useful when the server is bound from different sources with some sockets listening
334    /// on HTTP and some listening on HTTPS and the user should be presented with an enumeration of
335    /// which socket requires which protocol.
336    pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
337        self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
338    }
339
340    /// Resolves socket address(es) and binds server to created listener(s).
341    ///
342    /// # Hostname Resolution
343    ///
344    /// When `addrs` includes a hostname, it is possible for this method to bind to both the IPv4
345    /// and IPv6 addresses that result from a DNS lookup. You can test this by passing
346    /// `localhost:8080` and noting that the server binds to `127.0.0.1:8080` _and_ `[::1]:8080`. To
347    /// bind additional addresses, call this method multiple times.
348    ///
349    /// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
350    ///
351    /// # Worker Count
352    ///
353    /// The `factory` will be instantiated multiple times in most scenarios. The number of
354    /// instantiations is number of [`workers`](Self::workers()) × number of sockets resolved by
355    /// `addrs`.
356    ///
357    /// For example, if you've manually set [`workers`](Self::workers()) to 2, and use `127.0.0.1`
358    /// as the bind `addrs`, then `factory` will be instantiated twice. However, using `localhost`
359    /// as the bind `addrs` can often resolve to both `127.0.0.1` (IPv4) _and_ `::1` (IPv6), causing
360    /// the `factory` to be instantiated 4 times (2 workers × 2 bind addresses).
361    ///
362    /// Using a bind address of `0.0.0.0`, which signals to use all interfaces, may also multiple
363    /// the number of instantiations in a similar way.
364    ///
365    /// # Typical Usage
366    ///
367    /// In general, use `127.0.0.1:<port>` when testing locally and `0.0.0.0:<port>` when deploying
368    /// (with or without a reverse proxy or load balancer) so that the server is accessible.
369    ///
370    /// # Errors
371    ///
372    /// Returns an `io::Error` if:
373    /// - `addrs` cannot be resolved into one or more socket addresses;
374    /// - all the resolved socket addresses are already bound.
375    ///
376    /// # Example
377    ///
378    /// ```
379    /// # use actix_web::{App, HttpServer};
380    /// # fn inner() -> std::io::Result<()> {
381    /// HttpServer::new(|| App::new())
382    ///     .bind(("127.0.0.1", 8080))?
383    ///     .bind("[::1]:9000")?
384    /// # ; Ok(()) }
385    /// ```
386    pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
387        let sockets = bind_addrs(addrs, self.backlog)?;
388
389        for lst in sockets {
390            self = self.listen(lst)?;
391        }
392
393        Ok(self)
394    }
395
396    /// Resolves socket address(es) and binds server to created listener(s) for plaintext HTTP/1.x
397    /// or HTTP/2 connections.
398    ///
399    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
400    #[cfg(feature = "http2")]
401    pub fn bind_auto_h2c<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
402        let sockets = bind_addrs(addrs, self.backlog)?;
403
404        for lst in sockets {
405            self = self.listen_auto_h2c(lst)?;
406        }
407
408        Ok(self)
409    }
410
411    /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
412    /// using Rustls v0.20.
413    ///
414    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
415    ///
416    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
417    #[cfg(feature = "rustls-0_20")]
418    pub fn bind_rustls<A: net::ToSocketAddrs>(
419        mut self,
420        addrs: A,
421        config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
422    ) -> io::Result<Self> {
423        let sockets = bind_addrs(addrs, self.backlog)?;
424        for lst in sockets {
425            self = self.listen_rustls_0_20_inner(lst, config.clone())?;
426        }
427        Ok(self)
428    }
429
430    /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
431    /// using Rustls v0.21.
432    ///
433    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
434    ///
435    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
436    #[cfg(feature = "rustls-0_21")]
437    pub fn bind_rustls_021<A: net::ToSocketAddrs>(
438        mut self,
439        addrs: A,
440        config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
441    ) -> io::Result<Self> {
442        let sockets = bind_addrs(addrs, self.backlog)?;
443        for lst in sockets {
444            self = self.listen_rustls_0_21_inner(lst, config.clone())?;
445        }
446        Ok(self)
447    }
448
449    /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
450    /// using Rustls v0.22.
451    ///
452    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
453    ///
454    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
455    #[cfg(feature = "rustls-0_22")]
456    pub fn bind_rustls_0_22<A: net::ToSocketAddrs>(
457        mut self,
458        addrs: A,
459        config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
460    ) -> io::Result<Self> {
461        let sockets = bind_addrs(addrs, self.backlog)?;
462        for lst in sockets {
463            self = self.listen_rustls_0_22_inner(lst, config.clone())?;
464        }
465        Ok(self)
466    }
467
468    /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
469    /// using Rustls v0.23.
470    ///
471    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
472    ///
473    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
474    #[cfg(feature = "rustls-0_23")]
475    pub fn bind_rustls_0_23<A: net::ToSocketAddrs>(
476        mut self,
477        addrs: A,
478        config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
479    ) -> io::Result<Self> {
480        let sockets = bind_addrs(addrs, self.backlog)?;
481        for lst in sockets {
482            self = self.listen_rustls_0_23_inner(lst, config.clone())?;
483        }
484        Ok(self)
485    }
486
487    /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
488    /// using OpenSSL.
489    ///
490    /// See [`bind()`](Self::bind()) for more details on `addrs` argument.
491    ///
492    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
493    #[cfg(feature = "openssl")]
494    pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
495    where
496        A: net::ToSocketAddrs,
497    {
498        let sockets = bind_addrs(addrs, self.backlog)?;
499        let acceptor = openssl_acceptor(builder)?;
500
501        for lst in sockets {
502            self = self.listen_openssl_inner(lst, acceptor.clone())?;
503        }
504
505        Ok(self)
506    }
507
508    /// Binds to existing listener for accepting incoming connection requests.
509    ///
510    /// No changes are made to `lst`'s configuration. Ensure it is configured properly before
511    /// passing ownership to `listen()`.
512    pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
513        let cfg = Arc::clone(&self.config);
514        let factory = self.factory.clone();
515        let addr = lst.local_addr().unwrap();
516
517        self.sockets.push(Socket {
518            addr,
519            scheme: "http",
520        });
521
522        let on_connect_fn = self.on_connect_fn.clone();
523
524        self.builder =
525            self.builder
526                .listen(format!("actix-web-service-{}", addr), lst, move || {
527                    let cfg = cfg.lock().unwrap();
528                    let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
529
530                    let mut svc = HttpService::build()
531                        .keep_alive(cfg.keep_alive)
532                        .client_request_timeout(cfg.client_request_timeout)
533                        .client_disconnect_timeout(cfg.client_disconnect_timeout)
534                        .local_addr(addr);
535
536                    if let Some(handler) = on_connect_fn.clone() {
537                        svc =
538                            svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
539                    };
540
541                    let fac = factory()
542                        .into_factory()
543                        .map_err(|err| err.into().error_response());
544
545                    svc.finish(map_config(fac, move |_| {
546                        AppConfig::new(false, host.clone(), addr)
547                    }))
548                    .tcp()
549                })?;
550
551        Ok(self)
552    }
553
554    /// Binds to existing listener for accepting incoming plaintext HTTP/1.x or HTTP/2 connections.
555    #[cfg(feature = "http2")]
556    pub fn listen_auto_h2c(mut self, lst: net::TcpListener) -> io::Result<Self> {
557        let cfg = Arc::clone(&self.config);
558        let factory = self.factory.clone();
559        let addr = lst.local_addr().unwrap();
560
561        self.sockets.push(Socket {
562            addr,
563            scheme: "http",
564        });
565
566        let on_connect_fn = self.on_connect_fn.clone();
567
568        self.builder =
569            self.builder
570                .listen(format!("actix-web-service-{}", addr), lst, move || {
571                    let cfg = cfg.lock().unwrap();
572                    let host = cfg.host.clone().unwrap_or_else(|| format!("{}", addr));
573
574                    let mut svc = HttpService::build()
575                        .keep_alive(cfg.keep_alive)
576                        .client_request_timeout(cfg.client_request_timeout)
577                        .client_disconnect_timeout(cfg.client_disconnect_timeout)
578                        .local_addr(addr);
579
580                    if let Some(handler) = on_connect_fn.clone() {
581                        svc =
582                            svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
583                    };
584
585                    let fac = factory()
586                        .into_factory()
587                        .map_err(|err| err.into().error_response());
588
589                    svc.finish(map_config(fac, move |_| {
590                        AppConfig::new(false, host.clone(), addr)
591                    }))
592                    .tcp_auto_h2c()
593                })?;
594
595        Ok(self)
596    }
597
598    /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
599    /// v0.20.
600    ///
601    /// See [`listen()`](Self::listen) for more details on the `lst` argument.
602    ///
603    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
604    #[cfg(feature = "rustls-0_20")]
605    pub fn listen_rustls(
606        self,
607        lst: net::TcpListener,
608        config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
609    ) -> io::Result<Self> {
610        self.listen_rustls_0_20_inner(lst, config)
611    }
612
613    /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
614    /// v0.21.
615    ///
616    /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
617    ///
618    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
619    #[cfg(feature = "rustls-0_21")]
620    pub fn listen_rustls_0_21(
621        self,
622        lst: net::TcpListener,
623        config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
624    ) -> io::Result<Self> {
625        self.listen_rustls_0_21_inner(lst, config)
626    }
627
628    #[cfg(feature = "rustls-0_20")]
629    fn listen_rustls_0_20_inner(
630        mut self,
631        lst: net::TcpListener,
632        config: actix_tls::accept::rustls_0_20::reexports::ServerConfig,
633    ) -> io::Result<Self> {
634        let factory = self.factory.clone();
635        let cfg = Arc::clone(&self.config);
636        let addr = lst.local_addr().unwrap();
637        self.sockets.push(Socket {
638            addr,
639            scheme: "https",
640        });
641
642        let on_connect_fn = self.on_connect_fn.clone();
643
644        self.builder =
645            self.builder
646                .listen(format!("actix-web-service-{}", addr), lst, move || {
647                    let c = cfg.lock().unwrap();
648                    let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
649
650                    let svc = HttpService::build()
651                        .keep_alive(c.keep_alive)
652                        .client_request_timeout(c.client_request_timeout)
653                        .client_disconnect_timeout(c.client_disconnect_timeout);
654
655                    let svc = if let Some(handler) = on_connect_fn.clone() {
656                        svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
657                    } else {
658                        svc
659                    };
660
661                    let fac = factory()
662                        .into_factory()
663                        .map_err(|err| err.into().error_response());
664
665                    let acceptor_config = match c.tls_handshake_timeout {
666                        Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
667                        None => TlsAcceptorConfig::default(),
668                    };
669
670                    svc.finish(map_config(fac, move |_| {
671                        AppConfig::new(true, host.clone(), addr)
672                    }))
673                    .rustls_with_config(config.clone(), acceptor_config)
674                })?;
675
676        Ok(self)
677    }
678
679    #[cfg(feature = "rustls-0_21")]
680    fn listen_rustls_0_21_inner(
681        mut self,
682        lst: net::TcpListener,
683        config: actix_tls::accept::rustls_0_21::reexports::ServerConfig,
684    ) -> io::Result<Self> {
685        let factory = self.factory.clone();
686        let cfg = Arc::clone(&self.config);
687        let addr = lst.local_addr().unwrap();
688        self.sockets.push(Socket {
689            addr,
690            scheme: "https",
691        });
692
693        let on_connect_fn = self.on_connect_fn.clone();
694
695        self.builder =
696            self.builder
697                .listen(format!("actix-web-service-{}", addr), lst, move || {
698                    let c = cfg.lock().unwrap();
699                    let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
700
701                    let svc = HttpService::build()
702                        .keep_alive(c.keep_alive)
703                        .client_request_timeout(c.client_request_timeout)
704                        .client_disconnect_timeout(c.client_disconnect_timeout);
705
706                    let svc = if let Some(handler) = on_connect_fn.clone() {
707                        svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
708                    } else {
709                        svc
710                    };
711
712                    let fac = factory()
713                        .into_factory()
714                        .map_err(|err| err.into().error_response());
715
716                    let acceptor_config = match c.tls_handshake_timeout {
717                        Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
718                        None => TlsAcceptorConfig::default(),
719                    };
720
721                    svc.finish(map_config(fac, move |_| {
722                        AppConfig::new(true, host.clone(), addr)
723                    }))
724                    .rustls_021_with_config(config.clone(), acceptor_config)
725                })?;
726
727        Ok(self)
728    }
729
730    /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
731    /// v0.22.
732    ///
733    /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
734    ///
735    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
736    #[cfg(feature = "rustls-0_22")]
737    pub fn listen_rustls_0_22(
738        self,
739        lst: net::TcpListener,
740        config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
741    ) -> io::Result<Self> {
742        self.listen_rustls_0_22_inner(lst, config)
743    }
744
745    #[cfg(feature = "rustls-0_22")]
746    fn listen_rustls_0_22_inner(
747        mut self,
748        lst: net::TcpListener,
749        config: actix_tls::accept::rustls_0_22::reexports::ServerConfig,
750    ) -> io::Result<Self> {
751        let factory = self.factory.clone();
752        let cfg = Arc::clone(&self.config);
753        let addr = lst.local_addr().unwrap();
754        self.sockets.push(Socket {
755            addr,
756            scheme: "https",
757        });
758
759        let on_connect_fn = self.on_connect_fn.clone();
760
761        self.builder =
762            self.builder
763                .listen(format!("actix-web-service-{}", addr), lst, move || {
764                    let c = cfg.lock().unwrap();
765                    let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
766
767                    let svc = HttpService::build()
768                        .keep_alive(c.keep_alive)
769                        .client_request_timeout(c.client_request_timeout)
770                        .client_disconnect_timeout(c.client_disconnect_timeout);
771
772                    let svc = if let Some(handler) = on_connect_fn.clone() {
773                        svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
774                    } else {
775                        svc
776                    };
777
778                    let fac = factory()
779                        .into_factory()
780                        .map_err(|err| err.into().error_response());
781
782                    let acceptor_config = match c.tls_handshake_timeout {
783                        Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
784                        None => TlsAcceptorConfig::default(),
785                    };
786
787                    svc.finish(map_config(fac, move |_| {
788                        AppConfig::new(true, host.clone(), addr)
789                    }))
790                    .rustls_0_22_with_config(config.clone(), acceptor_config)
791                })?;
792
793        Ok(self)
794    }
795
796    /// Binds to existing listener for accepting incoming TLS connection requests using Rustls
797    /// v0.23.
798    ///
799    /// See [`listen()`](Self::listen()) for more details on the `lst` argument.
800    ///
801    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
802    #[cfg(feature = "rustls-0_23")]
803    pub fn listen_rustls_0_23(
804        self,
805        lst: net::TcpListener,
806        config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
807    ) -> io::Result<Self> {
808        self.listen_rustls_0_23_inner(lst, config)
809    }
810
811    #[cfg(feature = "rustls-0_23")]
812    fn listen_rustls_0_23_inner(
813        mut self,
814        lst: net::TcpListener,
815        config: actix_tls::accept::rustls_0_23::reexports::ServerConfig,
816    ) -> io::Result<Self> {
817        let factory = self.factory.clone();
818        let cfg = Arc::clone(&self.config);
819        let addr = lst.local_addr().unwrap();
820        self.sockets.push(Socket {
821            addr,
822            scheme: "https",
823        });
824
825        let on_connect_fn = self.on_connect_fn.clone();
826
827        self.builder =
828            self.builder
829                .listen(format!("actix-web-service-{}", addr), lst, move || {
830                    let c = cfg.lock().unwrap();
831                    let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
832
833                    let svc = HttpService::build()
834                        .keep_alive(c.keep_alive)
835                        .client_request_timeout(c.client_request_timeout)
836                        .client_disconnect_timeout(c.client_disconnect_timeout);
837
838                    let svc = if let Some(handler) = on_connect_fn.clone() {
839                        svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
840                    } else {
841                        svc
842                    };
843
844                    let fac = factory()
845                        .into_factory()
846                        .map_err(|err| err.into().error_response());
847
848                    let acceptor_config = match c.tls_handshake_timeout {
849                        Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
850                        None => TlsAcceptorConfig::default(),
851                    };
852
853                    svc.finish(map_config(fac, move |_| {
854                        AppConfig::new(true, host.clone(), addr)
855                    }))
856                    .rustls_0_23_with_config(config.clone(), acceptor_config)
857                })?;
858
859        Ok(self)
860    }
861
862    /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL.
863    ///
864    /// See [`listen()`](Self::listen) for more details on the `lst` argument.
865    ///
866    /// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
867    #[cfg(feature = "openssl")]
868    pub fn listen_openssl(
869        self,
870        lst: net::TcpListener,
871        builder: SslAcceptorBuilder,
872    ) -> io::Result<Self> {
873        self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
874    }
875
876    #[cfg(feature = "openssl")]
877    fn listen_openssl_inner(
878        mut self,
879        lst: net::TcpListener,
880        acceptor: SslAcceptor,
881    ) -> io::Result<Self> {
882        let factory = self.factory.clone();
883        let cfg = Arc::clone(&self.config);
884        let addr = lst.local_addr().unwrap();
885        self.sockets.push(Socket {
886            addr,
887            scheme: "https",
888        });
889
890        let on_connect_fn = self.on_connect_fn.clone();
891
892        self.builder =
893            self.builder
894                .listen(format!("actix-web-service-{}", addr), lst, move || {
895                    let c = cfg.lock().unwrap();
896                    let host = c.host.clone().unwrap_or_else(|| format!("{}", addr));
897
898                    let svc = HttpService::build()
899                        .keep_alive(c.keep_alive)
900                        .client_request_timeout(c.client_request_timeout)
901                        .client_disconnect_timeout(c.client_disconnect_timeout)
902                        .local_addr(addr);
903
904                    let svc = if let Some(handler) = on_connect_fn.clone() {
905                        svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext))
906                    } else {
907                        svc
908                    };
909
910                    let fac = factory()
911                        .into_factory()
912                        .map_err(|err| err.into().error_response());
913
914                    // false positive lint (?)
915                    #[allow(clippy::significant_drop_in_scrutinee)]
916                    let acceptor_config = match c.tls_handshake_timeout {
917                        Some(dur) => TlsAcceptorConfig::default().handshake_timeout(dur),
918                        None => TlsAcceptorConfig::default(),
919                    };
920
921                    svc.finish(map_config(fac, move |_| {
922                        AppConfig::new(true, host.clone(), addr)
923                    }))
924                    .openssl_with_config(acceptor.clone(), acceptor_config)
925                })?;
926
927        Ok(self)
928    }
929
930    /// Opens Unix Domain Socket (UDS) from `uds` path and binds server to created listener.
931    #[cfg(unix)]
932    pub fn bind_uds<A>(mut self, uds_path: A) -> io::Result<Self>
933    where
934        A: AsRef<std::path::Path>,
935    {
936        use actix_http::Protocol;
937        use actix_rt::net::UnixStream;
938        use actix_service::{fn_service, ServiceFactoryExt as _};
939
940        let cfg = Arc::clone(&self.config);
941        let factory = self.factory.clone();
942        let socket_addr =
943            net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
944
945        self.sockets.push(Socket {
946            scheme: "http",
947            addr: socket_addr,
948        });
949
950        self.builder = self.builder.bind_uds(
951            format!("actix-web-service-{:?}", uds_path.as_ref()),
952            uds_path,
953            move || {
954                let c = cfg.lock().unwrap();
955                let config = AppConfig::new(
956                    false,
957                    c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
958                    socket_addr,
959                );
960
961                let fac = factory()
962                    .into_factory()
963                    .map_err(|err| err.into().error_response());
964
965                fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then(
966                    HttpService::build()
967                        .keep_alive(c.keep_alive)
968                        .client_request_timeout(c.client_request_timeout)
969                        .client_disconnect_timeout(c.client_disconnect_timeout)
970                        .finish(map_config(fac, move |_| config.clone())),
971                )
972            },
973        )?;
974
975        Ok(self)
976    }
977
978    /// Binds to existing Unix Domain Socket (UDS) listener.
979    #[cfg(unix)]
980    pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
981        use actix_http::Protocol;
982        use actix_rt::net::UnixStream;
983        use actix_service::{fn_service, ServiceFactoryExt as _};
984
985        let cfg = Arc::clone(&self.config);
986        let factory = self.factory.clone();
987        let socket_addr =
988            net::SocketAddr::new(net::IpAddr::V4(net::Ipv4Addr::new(127, 0, 0, 1)), 8080);
989        self.sockets.push(Socket {
990            scheme: "http",
991            addr: socket_addr,
992        });
993
994        let addr = lst.local_addr()?;
995        let name = format!("actix-web-service-{:?}", addr);
996        let on_connect_fn = self.on_connect_fn.clone();
997
998        self.builder = self.builder.listen_uds(name, lst, move || {
999            let c = cfg.lock().unwrap();
1000            let config = AppConfig::new(
1001                false,
1002                c.host.clone().unwrap_or_else(|| format!("{}", socket_addr)),
1003                socket_addr,
1004            );
1005
1006            fn_service(|io: UnixStream| async { Ok((io, Protocol::Http1, None)) }).and_then({
1007                let mut svc = HttpService::build()
1008                    .keep_alive(c.keep_alive)
1009                    .client_request_timeout(c.client_request_timeout)
1010                    .client_disconnect_timeout(c.client_disconnect_timeout);
1011
1012                if let Some(handler) = on_connect_fn.clone() {
1013                    svc = svc.on_connect_ext(move |io: &_, ext: _| (handler)(io as &dyn Any, ext));
1014                }
1015
1016                let fac = factory()
1017                    .into_factory()
1018                    .map_err(|err| err.into().error_response());
1019
1020                svc.finish(map_config(fac, move |_| config.clone()))
1021            })
1022        })?;
1023        Ok(self)
1024    }
1025}
1026
1027impl<F, I, S, B> HttpServer<F, I, S, B>
1028where
1029    F: Fn() -> I + Send + Clone + 'static,
1030    I: IntoServiceFactory<S, Request>,
1031    S: ServiceFactory<Request, Config = AppConfig>,
1032    S::Error: Into<Error>,
1033    S::InitError: fmt::Debug,
1034    S::Response: Into<Response<B>>,
1035    S::Service: 'static,
1036    B: MessageBody,
1037{
1038    /// Start listening for incoming connections.
1039    ///
1040    /// # Workers
1041    /// This method starts a number of HTTP workers in separate threads. The number of workers in a
1042    /// set is defined by [`workers()`](Self::workers) or, by default, the number of the machine's
1043    /// physical cores. One worker set is created for each socket address to be bound. For example,
1044    /// if workers is set to 4, and there are 2 addresses to bind, then 8 worker threads will be
1045    /// spawned.
1046    ///
1047    /// # Panics
1048    /// This methods panics if no socket addresses were successfully bound or if no Tokio runtime
1049    /// is set up.
1050    pub fn run(self) -> Server {
1051        self.builder.run()
1052    }
1053}
1054
1055/// Bind TCP listeners to socket addresses resolved from `addrs` with options.
1056fn bind_addrs(addrs: impl net::ToSocketAddrs, backlog: u32) -> io::Result<Vec<net::TcpListener>> {
1057    let mut err = None;
1058    let mut success = false;
1059    let mut sockets = Vec::new();
1060
1061    for addr in addrs.to_socket_addrs()? {
1062        match create_tcp_listener(addr, backlog) {
1063            Ok(lst) => {
1064                success = true;
1065                sockets.push(lst);
1066            }
1067            Err(error) => err = Some(error),
1068        }
1069    }
1070
1071    if success {
1072        Ok(sockets)
1073    } else if let Some(err) = err.take() {
1074        Err(err)
1075    } else {
1076        Err(io::Error::new(
1077            io::ErrorKind::Other,
1078            "Can not bind to address.",
1079        ))
1080    }
1081}
1082
1083/// Creates a TCP listener from socket address and options.
1084fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
1085    use socket2::{Domain, Protocol, Socket, Type};
1086    let domain = Domain::for_address(addr);
1087    let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))?;
1088    #[cfg(not(windows))]
1089    {
1090        socket.set_reuse_address(true)?;
1091    }
1092    socket.bind(&addr.into())?;
1093    // clamp backlog to max u32 that fits in i32 range
1094    let backlog = cmp::min(backlog, i32::MAX as u32) as i32;
1095    socket.listen(backlog)?;
1096    Ok(net::TcpListener::from(socket))
1097}
1098
1099/// Configures OpenSSL acceptor `builder` with ALPN protocols.
1100#[cfg(feature = "openssl")]
1101fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
1102    builder.set_alpn_select_callback(|_, protocols| {
1103        const H2: &[u8] = b"\x02h2";
1104        const H11: &[u8] = b"\x08http/1.1";
1105
1106        if protocols.windows(3).any(|window| window == H2) {
1107            Ok(b"h2")
1108        } else if protocols.windows(9).any(|window| window == H11) {
1109            Ok(b"http/1.1")
1110        } else {
1111            Err(AlpnError::NOACK)
1112        }
1113    });
1114
1115    builder.set_alpn_protos(b"\x08http/1.1\x02h2")?;
1116
1117    Ok(builder.build())
1118}