actix_web/
server.rs

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