1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-26 11:31:09 +00:00

improve HttpServer docs

This commit is contained in:
Rob Ede 2022-07-31 21:58:15 +01:00
parent 4bbe60b609
commit 10746fb2fb
No known key found for this signature in database
GPG key ID: 97C636207D3EF933

View file

@ -41,17 +41,22 @@ struct Config {
/// ///
/// Create new HTTP server with application factory. /// Create new HTTP server with application factory.
/// ///
/// # HTTP/2
/// Currently, HTTP/2 is only supported when using TLS (HTTPS). See `bind_rustls` or `bind_openssl`.
///
/// # Examples
/// ```no_run /// ```no_run
/// use actix_web::{web, App, HttpResponse, HttpServer}; /// use actix_web::{web, App, HttpResponse, HttpServer};
/// ///
/// #[actix_rt::main] /// #[actix_web::main]
/// async fn main() -> std::io::Result<()> { /// async fn main() -> std::io::Result<()> {
/// HttpServer::new( /// HttpServer::new(|| {
/// || App::new() /// App::new()
/// .service(web::resource("/").to(|| HttpResponse::Ok()))) /// .service(web::resource("/").to(|| async { "hello world" }))
/// .bind("127.0.0.1:59090")? /// })
/// .run() /// .bind(("127.0.0.1", 8080))?
/// .await /// .run()
/// .await
/// } /// }
/// ``` /// ```
pub struct HttpServer<F, I, S, B> pub struct HttpServer<F, I, S, B>
@ -133,7 +138,7 @@ where
} }
} }
/// Set number of workers to start. /// Sets number of workers to start (per bind address).
/// ///
/// By default, the number of available physical CPUs is used as the worker count. /// By default, the number of available physical CPUs is used as the worker count.
pub fn workers(mut self, num: usize) -> Self { pub fn workers(mut self, num: usize) -> Self {
@ -141,7 +146,7 @@ where
self self
} }
/// Set the maximum number of pending connections. /// Sets the maximum number of pending connections.
/// ///
/// This refers to the number of clients that can be waiting to be served. /// This refers to the number of clients that can be waiting to be served.
/// Exceeding this number results in the client getting an error when /// Exceeding this number results in the client getting an error when
@ -157,7 +162,7 @@ where
self self
} }
/// Sets the maximum per-worker number of concurrent connections. /// Sets the per-worker maximum number of concurrent connections.
/// ///
/// All socket listeners will stop accepting connections when this limit is reached for /// All socket listeners will stop accepting connections when this limit is reached for
/// each worker. /// each worker.
@ -168,7 +173,7 @@ where
self self
} }
/// Sets the maximum per-worker concurrent connection establish process. /// Sets the per-worker maximum concurrent TLS connection limit.
/// ///
/// All listeners will stop accepting connections when this limit is reached. It can be used to /// All listeners will stop accepting connections when this limit is reached. It can be used to
/// limit the global TLS CPU usage. /// limit the global TLS CPU usage.
@ -181,7 +186,7 @@ where
self self
} }
/// Set max number of threads for each worker's blocking task thread pool. /// Sets max number of threads for each worker's blocking task thread pool.
/// ///
/// One thread pool is set up **per worker**; not shared across workers. /// One thread pool is set up **per worker**; not shared across workers.
/// ///
@ -191,7 +196,7 @@ where
self self
} }
/// Set server keep-alive setting. /// Sets server keep-alive preference.
/// ///
/// By default keep alive is set to a 5 seconds. /// By default keep alive is set to a 5 seconds.
pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self { pub fn keep_alive<T: Into<KeepAlive>>(self, val: T) -> Self {
@ -199,11 +204,10 @@ where
self self
} }
/// Set server client timeout in milliseconds for first request. /// Sets server client timeout for first request.
/// ///
/// Defines a timeout for reading client request header. If a client does not transmit /// Defines a timeout for reading client request head. If a client does not transmit the entire
/// the entire set headers within this time, the request is terminated with /// set headers within this time, the request is terminated with a 408 (Request Timeout) error.
/// the 408 (Request Time-out) error.
/// ///
/// To disable timeout set value to 0. /// To disable timeout set value to 0.
/// ///
@ -219,10 +223,10 @@ where
self.client_request_timeout(dur) self.client_request_timeout(dur)
} }
/// Set server connection shutdown timeout in milliseconds. /// Sets server connection shutdown timeout.
/// ///
/// Defines a timeout for shutdown connection. If a shutdown procedure does not complete /// Defines a timeout for connection shutdown. If a shutdown procedure does not complete within
/// within this time, the request is dropped. /// this time, the request is dropped.
/// ///
/// To disable timeout set value to 0. /// To disable timeout set value to 0.
/// ///
@ -232,10 +236,10 @@ where
self self
} }
/// Set TLS handshake timeout. /// Sets TLS handshake timeout.
/// ///
/// Defines a timeout for TLS handshake. If the TLS handshake does not complete /// Defines a timeout for TLS handshake. If the TLS handshake does not complete within this
/// within this time, the connection is closed. /// time, the connection is closed.
/// ///
/// By default handshake timeout is set to 3000 milliseconds. /// By default handshake timeout is set to 3000 milliseconds.
#[cfg(any(feature = "openssl", feature = "rustls"))] #[cfg(any(feature = "openssl", feature = "rustls"))]
@ -256,35 +260,35 @@ where
self.client_disconnect_timeout(Duration::from_millis(dur)) self.client_disconnect_timeout(Duration::from_millis(dur))
} }
/// Set server host name. /// Sets server host name.
/// ///
/// Host name is used by application router as a hostname for url generation. /// Host name is used by application router as a hostname for url generation. Check
/// Check [ConnectionInfo](super::dev::ConnectionInfo::host()) /// [`ConnectionInfo`](crate::dev::ConnectionInfo::host()) docs for more info.
/// documentation for more information.
/// ///
/// By default host name is set to a "localhost" value. /// By default, hostname is set to "localhost".
pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self { pub fn server_hostname<T: AsRef<str>>(self, val: T) -> Self {
self.config.lock().unwrap().host = Some(val.as_ref().to_owned()); self.config.lock().unwrap().host = Some(val.as_ref().to_owned());
self self
} }
/// Stop Actix `System` after server shutdown. /// Stops `actix_rt` `System` after server shutdown.
///
/// Does nothing when running under `#[tokio::main]` runtime.
pub fn system_exit(mut self) -> Self { pub fn system_exit(mut self) -> Self {
self.builder = self.builder.system_exit(); self.builder = self.builder.system_exit();
self self
} }
/// Disable signal handling /// Disables signal handling.
pub fn disable_signals(mut self) -> Self { pub fn disable_signals(mut self) -> Self {
self.builder = self.builder.disable_signals(); self.builder = self.builder.disable_signals();
self self
} }
/// Timeout for graceful workers shutdown. /// Sets timeout for graceful worker shutdown of workers.
/// ///
/// After receiving a stop signal, workers have this much time to finish /// After receiving a stop signal, workers have this much time to finish serving requests.
/// serving requests. Workers still alive after the timeout are force /// Workers still alive after the timeout are force dropped.
/// dropped.
/// ///
/// By default shutdown timeout sets to 30 seconds. /// By default shutdown timeout sets to 30 seconds.
pub fn shutdown_timeout(mut self, sec: u64) -> Self { pub fn shutdown_timeout(mut self, sec: u64) -> Self {
@ -292,33 +296,34 @@ where
self self
} }
/// Get addresses of bound sockets. /// Returns addresses of bound sockets.
pub fn addrs(&self) -> Vec<net::SocketAddr> { pub fn addrs(&self) -> Vec<net::SocketAddr> {
self.sockets.iter().map(|s| s.addr).collect() self.sockets.iter().map(|s| s.addr).collect()
} }
/// Get addresses of bound sockets and the scheme for it. /// Returns addresses of bound sockets and the scheme for it.
/// ///
/// This is useful when the server is bound from different sources /// This is useful when the server is bound from different sources with some sockets listening
/// with some sockets listening on HTTP and some listening on HTTPS /// on HTTP and some listening on HTTPS and the user should be presented with an enumeration of
/// and the user should be presented with an enumeration of which /// which socket requires which protocol.
/// socket requires which protocol.
pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> { pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
self.sockets.iter().map(|s| (s.addr, s.scheme)).collect() self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
} }
/// Use listener for accepting incoming connection requests /// Binds to existing listener for accepting incoming connection requests.
/// ///
/// HttpServer does not change any configuration for TcpListener, /// No changes are made to `lst`'s configuration. Ensure it is configured properly before
/// it needs to be configured before passing it to listen() method. /// passing ownership to `listen()`.
pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> { pub fn listen(mut self, lst: net::TcpListener) -> io::Result<Self> {
let cfg = self.config.clone(); let cfg = self.config.clone();
let factory = self.factory.clone(); let factory = self.factory.clone();
let addr = lst.local_addr().unwrap(); let addr = lst.local_addr().unwrap();
self.sockets.push(Socket { self.sockets.push(Socket {
addr, addr,
scheme: "http", scheme: "http",
}); });
let on_connect_fn = self.on_connect_fn.clone(); let on_connect_fn = self.on_connect_fn.clone();
self.builder = self.builder =
@ -351,20 +356,23 @@ where
Ok(self) Ok(self)
} }
#[cfg(feature = "openssl")] /// Binds to existing listener for accepting incoming TLS connection requests using OpenSSL.
/// Use listener for accepting incoming tls connection requests
/// ///
/// This method sets alpn protocols to "h2" and "http/1.1" /// See [listen()](Self::listen) for more details on the `lst` argument.
///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "openssl")]
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
pub fn listen_openssl( pub fn listen_openssl(
self, self,
lst: net::TcpListener, lst: net::TcpListener,
builder: SslAcceptorBuilder, builder: SslAcceptorBuilder,
) -> io::Result<Self> { ) -> io::Result<Self> {
self.listen_ssl_inner(lst, openssl_acceptor(builder)?) self.listen_openssl_inner(lst, openssl_acceptor(builder)?)
} }
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
fn listen_ssl_inner( fn listen_openssl_inner(
mut self, mut self,
lst: net::TcpListener, lst: net::TcpListener,
acceptor: SslAcceptor, acceptor: SslAcceptor,
@ -417,10 +425,13 @@ where
Ok(self) Ok(self)
} }
#[cfg(feature = "rustls")] /// Binds to existing listening for accepting incoming TLS connection requests using Rustls.
/// Use listener for accepting incoming tls connection requests
/// ///
/// This method prepends alpn protocols "h2" and "http/1.1" to configured ones /// See [listen()](Self::listen) for more details on the `lst` argument.
///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
pub fn listen_rustls( pub fn listen_rustls(
self, self,
lst: net::TcpListener, lst: net::TcpListener,
@ -480,11 +491,36 @@ where
Ok(self) Ok(self)
} }
/// The socket address to bind /// Resolves socket address(es) and binds server to created listener(s).
/// ///
/// To bind multiple addresses this method can be called multiple times. /// # Hostname Resolution
pub fn bind<A: net::ToSocketAddrs>(mut self, addr: A) -> io::Result<Self> { /// When `addr` includes a hostname, it is possible for this method to bind to both the IPv4 and
let sockets = self.bind2(addr)?; /// IPv6 addresses that result from a DNS lookup. You can test this by passing `localhost:8080`
/// and noting that the server binds to `127.0.0.1:8080` _and_ `[::1]:8080`. To bind additional
/// addresses, call this method multiple times.
///
/// Note that, if a DNS lookup is required, resolving hostnames is a blocking operation.
///
/// # Typical Usage
/// In general, use `127.0.0.1:<port>` when testing locally and `0.0.0.0:<port>` when deploying
/// (with or without a reverse proxy or load balancer) so that the server is accessible.
///
/// # Errors
/// Returns an `io::Error` if:
/// - `addrs` cannot be resolved into one or more socket addresses;
/// - all the resolved socket addresses are already bound.
///
/// # Example
/// ```
/// # use actix_web::{App, HttpServer};
/// # fn inner() -> std::io::Result<()> {
/// HttpServer::new(|| App::new())
/// .bind(("127.0.0.1", 8080))?
/// .bind("[::1]:9000")?
/// # ; Ok(()) }
/// ```
pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
let sockets = self.bind2(addrs)?;
for lst in sockets { for lst in sockets {
self = self.listen(lst)?; self = self.listen(lst)?;
@ -493,12 +529,12 @@ where
Ok(self) Ok(self)
} }
fn bind2<A: net::ToSocketAddrs>(&self, addr: A) -> io::Result<Vec<net::TcpListener>> { fn bind2<A: net::ToSocketAddrs>(&self, addrs: A) -> io::Result<Vec<net::TcpListener>> {
let mut err = None; let mut err = None;
let mut success = false; let mut success = false;
let mut sockets = Vec::new(); let mut sockets = Vec::new();
for addr in addr.to_socket_addrs()? { for addr in addrs.to_socket_addrs()? {
match create_tcp_listener(addr, self.backlog) { match create_tcp_listener(addr, self.backlog) {
Ok(lst) => { Ok(lst) => {
success = true; success = true;
@ -520,42 +556,50 @@ where
} }
} }
#[cfg(feature = "openssl")] /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
/// Start listening for incoming tls connections. /// using OpenSSL.
/// ///
/// This method sets alpn protocols to "h2" and "http/1.1" /// See [bind()](Self::bind) for more details on `addrs` argument.
pub fn bind_openssl<A>(mut self, addr: A, builder: SslAcceptorBuilder) -> io::Result<Self> ///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "openssl")]
#[cfg_attr(docsrs, doc(cfg(feature = "openssl")))]
pub fn bind_openssl<A>(mut self, addrs: A, builder: SslAcceptorBuilder) -> io::Result<Self>
where where
A: net::ToSocketAddrs, A: net::ToSocketAddrs,
{ {
let sockets = self.bind2(addr)?; let sockets = self.bind2(addrs)?;
let acceptor = openssl_acceptor(builder)?; let acceptor = openssl_acceptor(builder)?;
for lst in sockets { for lst in sockets {
self = self.listen_ssl_inner(lst, acceptor.clone())?; self = self.listen_openssl_inner(lst, acceptor.clone())?;
} }
Ok(self) Ok(self)
} }
#[cfg(feature = "rustls")] /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
/// Start listening for incoming tls connections. /// using Rustls.
/// ///
/// This method prepends alpn protocols "h2" and "http/1.1" to configured ones /// See [bind()](Self::bind) for more details on `addrs` argument.
///
/// ALPN protocols "h2" and "http/1.1" are added to any configured ones.
#[cfg(feature = "rustls")]
#[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
pub fn bind_rustls<A: net::ToSocketAddrs>( pub fn bind_rustls<A: net::ToSocketAddrs>(
mut self, mut self,
addr: A, addrs: A,
config: RustlsServerConfig, config: RustlsServerConfig,
) -> io::Result<Self> { ) -> io::Result<Self> {
let sockets = self.bind2(addr)?; let sockets = self.bind2(addrs)?;
for lst in sockets { for lst in sockets {
self = self.listen_rustls_inner(lst, config.clone())?; self = self.listen_rustls_inner(lst, config.clone())?;
} }
Ok(self) Ok(self)
} }
#[cfg(unix)]
/// Start listening for unix domain (UDS) connections on existing listener. /// Start listening for unix domain (UDS) connections on existing listener.
#[cfg(unix)]
pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> { pub fn listen_uds(mut self, lst: std::os::unix::net::UnixListener) -> io::Result<Self> {
use actix_http::Protocol; use actix_http::Protocol;
use actix_rt::net::UnixStream; use actix_rt::net::UnixStream;
@ -665,25 +709,16 @@ where
{ {
/// Start listening for incoming connections. /// Start listening for incoming connections.
/// ///
/// This method starts number of HTTP workers in separate threads. /// # Workers
/// For each address this method starts separate thread which does /// This method starts a number of HTTP workers in separate threads. The number of workers in a
/// `accept()` in a loop. /// set is defined by [`workers()`](Self::workers) or, by default, the number of the machine's
/// physical cores. One worker set is created for each socket address to be bound. For example,
/// if workers is set to 4, and there are 2 addresses to bind, then 8 worker threads will be
/// spawned.
/// ///
/// This methods panics if no socket address can be bound or an `Actix` system is not yet /// # Panics
/// configured. /// This methods panics if no socket addresses were successfully bound or if no Tokio runtime
/// /// is set up.
/// ```no_run
/// use std::io;
/// use actix_web::{web, App, HttpResponse, HttpServer};
///
/// #[actix_rt::main]
/// async fn main() -> io::Result<()> {
/// HttpServer::new(|| App::new().service(web::resource("/").to(|| HttpResponse::Ok())))
/// .bind("127.0.0.1:0")?
/// .run()
/// .await
/// }
/// ```
pub fn run(self) -> Server { pub fn run(self) -> Server {
self.builder.run() self.builder.run()
} }