1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-09 02:19:49 +00:00
actix-web/guide/src/qs_3_5.md

232 lines
7.3 KiB
Markdown
Raw Normal View History

2017-12-14 05:44:16 +00:00
# Server
2017-12-30 20:13:23 +00:00
[*HttpServer*](../actix_web/struct.HttpServer.html) type is responsible for
serving http requests. *HttpServer* accept application factory as a parameter,
Application factory must have `Send` + `Sync` bounderies. More about that in
2017-12-19 02:56:58 +00:00
*multi-threading* section. To bind to specific socket address `bind()` must be used.
This method could be called multiple times. To start http server one of the *start*
methods could be used. `start()` method start simple server, `start_tls()` or `start_ssl()`
starts ssl server. *HttpServer* is an actix actor, it has to be initialized
within properly configured actix system:
```rust
# extern crate actix;
# extern crate actix_web;
use actix::*;
use actix_web::*;
fn main() {
let sys = actix::System::new("guide");
HttpServer::new(
|| Application::new()
2017-12-21 07:21:26 +00:00
.resource("/", |r| r.h(httpcodes::HTTPOk)))
2017-12-19 02:56:58 +00:00
.bind("127.0.0.1:59080").unwrap()
2017-12-19 17:08:36 +00:00
.start();
2017-12-19 02:56:58 +00:00
# actix::Arbiter::system().send(actix::msgs::SystemExit(0));
let _ = sys.run();
}
```
2017-12-14 06:36:28 +00:00
2017-12-28 01:49:10 +00:00
It is possible to start server in separate thread with *spawn()* method. In that
case server spawns new thread and create new actix system in it. To stop
this server send `StopServer` message.
Http server is implemented as an actix actor. It is possible to communicate with server
via messaging system. All start methods like `start()`, `start_ssl()`, etc returns
address of the started http server. Actix http server accept several messages:
* `PauseServer` - Pause accepting incoming connections
* `ResumeServer` - Resume accepting incoming connections
* `StopServer` - Stop incoming connection processing, stop all workers and exit
```rust
# extern crate futures;
# extern crate actix;
# extern crate actix_web;
# use futures::Future;
use actix_web::*;
fn main() {
let addr = HttpServer::new(
|| Application::new()
.resource("/", |r| r.h(httpcodes::HTTPOk)))
.bind("127.0.0.1:0").expect("Can not bind to 127.0.0.1:0")
.spawn();
2017-12-30 20:13:23 +00:00
2017-12-28 20:27:46 +00:00
let _ = addr.call_fut(dev::StopServer{graceful: true}).wait(); // <- Send `StopServer` message to server.
2017-12-28 01:49:10 +00:00
}
```
2017-12-18 21:06:41 +00:00
2017-12-14 05:44:16 +00:00
## Multi-threading
Http server automatically starts number of http workers, by default
this number is equal to number of logical cpu in the system. This number
2017-12-15 04:12:28 +00:00
could be overridden with `HttpServer::threads()` method.
2017-12-14 05:44:16 +00:00
```rust
# extern crate actix_web;
# extern crate tokio_core;
# use tokio_core::net::TcpStream;
# use std::net::SocketAddr;
use actix_web::*;
fn main() {
HttpServer::<TcpStream, SocketAddr, _, _>::new(
|| Application::new()
2017-12-21 07:21:26 +00:00
.resource("/", |r| r.h(httpcodes::HTTPOk)))
2017-12-20 02:44:17 +00:00
.threads(4); // <- Start 4 workers
2017-12-14 05:44:16 +00:00
}
```
Server create separate application instance for each created worker. Application state
is not shared between threads, to share state `Arc` could be used. Application state
does not need to be `Send` and `Sync` but application factory must be `Send` + `Sync`.
2017-12-14 05:56:30 +00:00
## SSL
There are two `tls` and `alpn` features for ssl server. `tls` feature is for `native-tls`
integration and `alpn` is for `openssl`.
```toml
[dependencies]
actix-web = { git = "https://github.com/actix/actix-web", features=["alpn"] }
```
```rust,ignore
use std::fs::File;
use actix_web::*;
fn main() {
let mut file = File::open("identity.pfx").unwrap();
let mut pkcs12 = vec![];
file.read_to_end(&mut pkcs12).unwrap();
let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap().parse("12345").unwrap();
HttpServer::new(
|| Application::new()
.resource("/index.html", |r| r.f(index)))
2017-12-19 17:08:36 +00:00
.bind("127.0.0.1:8080").unwrap()
.serve_ssl(pkcs12).unwrap();
2017-12-14 05:56:30 +00:00
}
```
2017-12-15 04:12:28 +00:00
Note on *HTTP/2.0* protocol over tls without prior knowledge, it requires
2017-12-14 05:56:30 +00:00
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
`openssl` has `alpn ` support.
2017-12-30 20:13:23 +00:00
Please check [example](https://github.com/actix/actix-web/tree/master/examples/tls)
2017-12-20 02:44:17 +00:00
for full example.
2017-12-14 05:56:30 +00:00
2017-12-14 05:44:16 +00:00
## Keep-Alive
2017-12-15 04:12:28 +00:00
Actix can wait for requests on a keep-alive connection. *Keep alive*
2017-12-14 05:44:16 +00:00
connection behavior is defined by server settings.
* `Some(75)` - enable 75 sec *keep alive* timer according request and response settings.
* `Some(0)` - disable *keep alive*.
* `None` - Use `SO_KEEPALIVE` socket option.
```rust
# extern crate actix_web;
# extern crate tokio_core;
# use tokio_core::net::TcpStream;
# use std::net::SocketAddr;
use actix_web::*;
fn main() {
HttpServer::<TcpStream, SocketAddr, _, _>::new(||
Application::new()
2017-12-21 07:21:26 +00:00
.resource("/", |r| r.h(httpcodes::HTTPOk)))
2017-12-14 05:44:16 +00:00
.keep_alive(None); // <- Use `SO_KEEPALIVE` socket option.
}
```
If first option is selected then *keep alive* state
calculated based on response's *connection-type*. By default
`HttpResponse::connection_type` is not defined in that case *keep alive*
defined by request's http version. Keep alive is off for *HTTP/1.0*
and is on for *HTTP/1.1* and "HTTP/2.0".
*Connection type* could be change with `HttpResponseBuilder::connection_type()` method.
```rust
# extern crate actix_web;
# use actix_web::httpcodes::*;
use actix_web::*;
fn index(req: HttpRequest) -> HttpResponse {
HTTPOk.build()
.connection_type(headers::ConnectionType::Close) // <- Close connection
2017-12-14 06:36:28 +00:00
.force_close() // <- Alternative method
2017-12-14 05:44:16 +00:00
.finish().unwrap()
}
# fn main() {}
```
2017-12-29 00:25:47 +00:00
## Graceful shutdown
Actix http server support graceful shutdown. After receiving a stop signal, workers
have specific amount of time to finish serving requests. Workers still alive after the
timeout are force dropped. By default shutdown timeout sets to 30 seconds.
You can change this parameter with `HttpServer::shutdown_timeout()` method.
2017-12-30 20:13:23 +00:00
You can send stop message to server with server address and specify if you what
2017-12-29 00:25:47 +00:00
graceful shutdown or not. `start()` or `spawn()` methods return address of the server.
```rust
# extern crate futures;
# extern crate actix;
# extern crate actix_web;
# use futures::Future;
use actix_web::*;
fn main() {
let addr = HttpServer::new(
|| Application::new()
.resource("/", |r| r.h(httpcodes::HTTPOk)))
.bind("127.0.0.1:0").expect("Can not bind to 127.0.0.1:0")
.shutdown_timeout(60) // <- Set shutdown timeout to 60 seconds
.spawn();
let _ = addr.call_fut(
dev::StopServer{graceful:true}).wait(); // <- Send `StopServer` message to server.
}
```
2018-01-05 21:30:21 +00:00
It is possible to use signals. *CTRL-C* is available on all OSs, other signals are
available on unix systems.
2017-12-29 00:25:47 +00:00
Then you can subscribe your server to unix signals. Http server handles three signals:
* *SIGINT* - Force shutdown workers
* *SIGTERM* - Graceful shutdown workers
* *SIGQUIT* - Force shutdown workers
```rust,ignore
# extern crate futures;
# extern crate actix;
# extern crate actix_web;
use actix_web::*;
use actix::actors::signal::{ProcessSignals, Subscribe};
fn main() {
let sys = actix::System::new("signals");
let addr = HttpServer::new(|| {
Application::new()
.resource("/", |r| r.h(httpcodes::HTTPOk))})
.bind("127.0.0.1:8080").unwrap()
.start();
// Subscribe to unix signals
2018-01-04 03:11:40 +00:00
let signals = actix::Arbiter::system_registry().get::<ProcessSignals>();
2017-12-29 00:25:47 +00:00
signals.send(Subscribe(addr.subscriber()));
println!("Started http server: 127.0.0.1:8080");
# actix::Arbiter::system().send(actix::msgs::SystemExit(0));
let _ = sys.run();
}
```