diff --git a/.vscode/settings.json b/.vscode/settings.json index 9401b20..2cae3c9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ - "actix" + "actix", + "rustls" ] } diff --git a/content/docs/server.md b/content/docs/server.md index 8a80f36..7d0caaa 100644 --- a/content/docs/server.md +++ b/content/docs/server.md @@ -16,7 +16,7 @@ To bind to a specific socket address, [`bind()`][bindmethod] must be used, and i The `run()` method returns an instance of the [`Server`][server] type. A `Server` must be `await`ed or `spawn`ed to start processing requests. It will complete when it receives a shutdown signal; Actix Web listens for system process signals by default. -The following example shows how to start the HTTP server in a separate thread. +The following example shows how to start the HTTP server in a Tokio task with manual commands and shutdown using a server handle. {{< include-example example="server" file="signals.rs" section="signals" >}} @@ -54,7 +54,7 @@ async fn my_handler() -> impl Responder { The same limitation applies to extractors as well. When a handler function receives an argument which implements `FromRequest`, and that implementation blocks the current thread, the worker thread will block when running the handler. Special attention must be given when implementing extractors for this very reason, and they should also be implemented asynchronously where needed. -## SSL +## TLS / HTTPS There are two features for the ssl server: `rustls` and `openssl`. The `rustls` feature is for `rustls` integration and `openssl` is for `openssl`. @@ -66,8 +66,6 @@ openssl = { version = "0.10" } {{< include-example example="server" file="ssl.rs" section="ssl" >}} -> **Note**: the _HTTP/2.0_ protocol requires [tls alpn][tlsalpn]. At the moment, only `openssl` has `alpn` support. For a full example, check out [examples/openssl][exampleopenssl]. - To create the key.pem and cert.pem use the command. **Fill in your own subject** ```bash @@ -83,19 +81,19 @@ $ openssl rsa -in key.pem -out nopass.pem ## Keep-Alive -Actix can wait for requests on a keep-alive connection. +Actix Web keeps connections open to wait for subsequent requests. > _keep alive_ connection behavior is defined by server settings. -- `75`, `Some(75)`, `KeepAlive::Timeout(75)` - enable 75 second _keep alive_ timer. -- `None` or `KeepAlive::Disabled` - disable _keep alive_. -- `KeepAlive::Tcp(75)` - use `SO_KEEPALIVE` socket option. +- `Duration::from_secs(75)` or `KeepAlive::Timeout(75)`: enables 75 second keep-alive timer. +- `KeepAlive::Os`: uses OS keep-alive. +- `None` or `KeepAlive::Disabled`: disables keep-alive. {{< include-example example="server" file="keep_alive.rs" section="keep-alive" >}} -If the first option above is selected, then _keep alive_ state is calculated based on the response's _connection-type_. By default `HttpResponse::connection_type` is not defined. In that case _keep alive_ is defined by the request's HTTP version. +If the first option above is selected, then _keep alive_ state is calculated based on the response's _connection-type_. By default `HttpResponse::connection_type` is not defined. In that case -keep-alive is defined by the request's HTTP version. -> _keep alive_ is **off** for _HTTP/1.0_ and is **on** for _HTTP/1.1_ and _HTTP/2.0_. +> Keep-alive is **off** for HTTP/1.0 and is **on** for HTTP/1.1 and HTTP/2.0. _Connection type_ can be changed with `HttpResponseBuilder::connection_type()` method. @@ -105,7 +103,7 @@ _Connection type_ can be changed with `HttpResponseBuilder::connection_type()` m `HttpServer` supports graceful shutdown. After receiving a stop signal, workers have a specific amount of time to finish serving requests. Any workers still alive after the timeout are force-dropped. By default the shutdown timeout is set to 30 seconds. You can change this parameter with the [`HttpServer::shutdown_timeout()`][shutdowntimeout] method. -`HttpServer` handles several OS signals. _CTRL-C_ is available on all OSs, other signals are available on unix systems. +`HttpServer` handles several OS signals. _CTRL-C_ is available on all OSes, other signals are available on unix systems. - _SIGINT_ - Force shutdown workers - _SIGTERM_ - Graceful shutdown workers diff --git a/examples/http2/Cargo.toml b/examples/http2/Cargo.toml index 40746c5..cb58c1c 100644 --- a/examples/http2/Cargo.toml +++ b/examples/http2/Cargo.toml @@ -4,5 +4,5 @@ version = "1.0.0" edition = "2018" [dependencies] -actix-web = { version = "3", features = ["openssl"] } +actix-web = { version = "4", features = ["openssl"] } openssl = { version = "0.10", features = ["v110"] } diff --git a/examples/server/Cargo.toml b/examples/server/Cargo.toml index 8e242df..ae2230c 100644 --- a/examples/server/Cargo.toml +++ b/examples/server/Cargo.toml @@ -5,6 +5,7 @@ workspace = "../" edition = "2018" [dependencies] -actix-web = { version = "3", features = ["openssl"] } +actix-web = { version = "4", features = ["openssl"] } futures = "0.3" openssl = "0.10" +tokio = { version = "1.16.1", features = ["full"] } diff --git a/examples/server/src/keep_alive.rs b/examples/server/src/keep_alive.rs index ccd6118..88798f9 100644 --- a/examples/server/src/keep_alive.rs +++ b/examples/server/src/keep_alive.rs @@ -1,19 +1,37 @@ +use actix_web::{ + body::MessageBody, + dev::{ServiceFactory, ServiceRequest, ServiceResponse}, + App, Error, +}; + +#[allow(dead_code)] +fn app() -> App< + impl ServiceFactory< + ServiceRequest, + Response = ServiceResponse, + Config = (), + InitError = (), + Error = Error, + >, +> { + App::new() +} + // -use actix_web::{web, App, HttpResponse, HttpServer}; +use actix_web::{http::KeepAlive, HttpServer}; +use std::time::Duration; #[actix_web::main] async fn main() -> std::io::Result<()> { - let one = HttpServer::new(|| App::new().route("/", web::get().to(HttpResponse::Ok))) - .keep_alive(75); // <- Set keep-alive to 75 seconds + // Set keep-alive to 75 seconds + let _one = HttpServer::new(app).keep_alive(Duration::from_secs(75)); - // let _two = HttpServer::new(|| { - // App::new().route("/", web::get().to(|| HttpResponse::Ok())) - // }) - // .keep_alive(); // <- Use `SO_KEEPALIVE` socket option. + // Use OS's keep-alive (usually quite long) + let _two = HttpServer::new(app).keep_alive(KeepAlive::Os); - let _three = HttpServer::new(|| App::new().route("/", web::get().to(HttpResponse::Ok))) - .keep_alive(None); // <- Disable keep-alive + // Disable keep-alive + let _three = HttpServer::new(app).keep_alive(None); - one.bind(("127.0.0.1", 8080))?.run().await + Ok(()) } // diff --git a/examples/server/src/signals.rs b/examples/server/src/signals.rs index 0a02ab5..fe8efd9 100644 --- a/examples/server/src/signals.rs +++ b/examples/server/src/signals.rs @@ -1,31 +1,34 @@ // -use actix_web::{rt::System, web, App, HttpResponse, HttpServer}; -use std::sync::mpsc; -use std::thread; +use actix_web::{web, App, HttpResponse, HttpServer}; +use std::io; -#[actix_web::main] -async fn main() { - let (tx, rx) = mpsc::channel(); +#[tokio::main] +async fn main() -> io::Result<()> { + let srv = HttpServer::new(|| App::new().route("/", web::get().to(HttpResponse::Ok))) + .bind(("127.0.0.1", 8080))? + .shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds + .run(); - thread::spawn(move || { - let sys = System::new("http-server"); + // obtain handle to server + let srv_handle = srv.handle(); - let srv = HttpServer::new(|| App::new().route("/", web::get().to(HttpResponse::Ok))) - .bind(("127.0.0.1", 8080))? - .shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds - .run(); - - let _ = tx.send(srv); - sys.run() - }); - - let srv = rx.recv().unwrap(); + // spawn server as Tokio task to start processing connections + tokio::spawn(srv); // pause accepting new connections - srv.pause().await; + srv_handle.pause().await; + // resume accepting new connections - srv.resume().await; - // stop server - srv.stop(true).await; + srv_handle.resume().await; + + // stop server gracefully + srv_handle.stop(true).await; + + Ok(()) } // + +#[allow(dead_code)] +fn run_main() { + let _ = main(); +}