Skip to main content

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