mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-24 08:22:59 +01:00
update guide
This commit is contained in:
parent
408ddf0be1
commit
b7cde3f4a9
@ -85,3 +85,5 @@ fn main() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
## User sessions
|
## User sessions
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# HTTP/2
|
# HTTP/2.0
|
||||||
|
|
||||||
Actix web automatically upgrades connection to *HTTP/2* if possible.
|
Actix web automatically upgrades connection to *HTTP/2.0* if possible.
|
||||||
|
|
||||||
## Negotiation
|
## Negotiation
|
||||||
|
|
||||||
*HTTP/2* protocol over tls without prior knowlage requires
|
*HTTP/2.0* protocol over tls without prior knowlage requires
|
||||||
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
||||||
`rust-openssl` has support. Turn on `alpn` feature to enable `alpn` negotiation.
|
`rust-openssl` has support. Turn on `alpn` feature to enable `alpn` negotiation.
|
||||||
With enable `alpn` feature `HttpServer` provides
|
With enable `alpn` feature `HttpServer` provides
|
||||||
@ -32,7 +32,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Upgrade to *HTTP/2* schema described in
|
Upgrade to *HTTP/2.0* schema described in
|
||||||
[rfc section 3.2](https://http2.github.io/http2-spec/#rfc.section.3.2) is not supported.
|
[rfc section 3.2](https://http2.github.io/http2-spec/#rfc.section.3.2) is not supported.
|
||||||
Starting *HTTP/2* with prior knowledge is supported for both clear text connection
|
Starting *HTTP/2* with prior knowledge is supported for both clear text connection
|
||||||
and tls connection. [rfc section 3.4](https://http2.github.io/http2-spec/#rfc.section.3.4)
|
and tls connection. [rfc section 3.4](https://http2.github.io/http2-spec/#rfc.section.3.4)
|
||||||
|
@ -49,7 +49,7 @@ request handler with the application's `resource` on a particular *HTTP method*
|
|||||||
# }
|
# }
|
||||||
# fn main() {
|
# fn main() {
|
||||||
let app = Application::new()
|
let app = Application::new()
|
||||||
.resource("/", |r| r.method(Method::GET).f(index))
|
.resource("/", |r| r.f(index))
|
||||||
.finish();
|
.finish();
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# Server
|
# Server
|
||||||
|
|
||||||
|
|
||||||
## Multi-threading
|
## Multi-threading
|
||||||
|
|
||||||
Http server automatically starts number of http workers, by default
|
Http server automatically starts number of http workers, by default
|
||||||
@ -52,7 +53,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Note on *HTTP/2* protocol over tls without prior knowlage, it requires
|
Note on *HTTP/2.0* protocol over tls without prior knowlage, it requires
|
||||||
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
[tls alpn](https://tools.ietf.org/html/rfc7301). At the moment only
|
||||||
`openssl` has `alpn ` support.
|
`openssl` has `alpn ` support.
|
||||||
|
|
||||||
@ -99,6 +100,7 @@ use actix_web::*;
|
|||||||
fn index(req: HttpRequest) -> HttpResponse {
|
fn index(req: HttpRequest) -> HttpResponse {
|
||||||
HTTPOk.build()
|
HTTPOk.build()
|
||||||
.connection_type(headers::ConnectionType::Close) // <- Close connection
|
.connection_type(headers::ConnectionType::Close) // <- Close connection
|
||||||
|
.force_close() // <- Alternative method
|
||||||
.finish().unwrap()
|
.finish().unwrap()
|
||||||
}
|
}
|
||||||
# fn main() {}
|
# fn main() {}
|
||||||
|
@ -82,3 +82,45 @@ fn main() {
|
|||||||
.finish();
|
.finish();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Chunked transfer encoding
|
||||||
|
|
||||||
|
Actix automatically decode *chunked* encoding. `HttpRequest::payload()` already contains
|
||||||
|
decoded bytes stream. If request payload compressed with one of supported
|
||||||
|
compression codecs (br, gzip, deflate) bytes stream get decompressed.
|
||||||
|
|
||||||
|
Chunked encoding on response could be enabled with `HttpResponseBuilder::chunked()` method.
|
||||||
|
But this takes effect only for `Body::Streaming(BodyStream)` or `Body::StreamingContext` bodies.
|
||||||
|
Also if response payload compression is enabled and streaming body is used, chunked encoding
|
||||||
|
get enabled automatically.
|
||||||
|
|
||||||
|
Enabling chunked encoding for *HTTP/2.0* responses is forbidden.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# extern crate actix_web;
|
||||||
|
use actix_web::*;
|
||||||
|
use actix_web::headers::ContentEncoding;
|
||||||
|
|
||||||
|
fn index(req: HttpRequest) -> HttpResponse {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.chunked()
|
||||||
|
.body(Body::Streaming(Payload::empty().stream())).unwrap()
|
||||||
|
}
|
||||||
|
# fn main() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cookies
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
|
||||||
|
## Multipart body
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
|
||||||
|
## Urlencoded body
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
|
||||||
|
## Streaming request
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
@ -1 +1,4 @@
|
|||||||
# WebSockets
|
# WebSockets
|
||||||
|
|
||||||
|
[WIP]
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ use futures::Stream;
|
|||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
pub(crate) type BodyStream = Box<Stream<Item=Bytes, Error=Error>>;
|
/// Type represent streaming body
|
||||||
|
pub type BodyStream = Box<Stream<Item=Bytes, Error=Error>>;
|
||||||
|
|
||||||
/// Represents various types of http message body.
|
/// Represents various types of http message body.
|
||||||
pub enum Body {
|
pub enum Body {
|
||||||
|
@ -213,6 +213,9 @@ impl From<IoError> for PayloadError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `InternalServerError` for `PayloadError`
|
||||||
|
impl ResponseError for PayloadError {}
|
||||||
|
|
||||||
/// Return `BadRequest` for `cookie::ParseError`
|
/// Return `BadRequest` for `cookie::ParseError`
|
||||||
impl ResponseError for cookie::ParseError {
|
impl ResponseError for cookie::ParseError {
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
|
@ -254,7 +254,7 @@ impl<T, H> Http1<T, H>
|
|||||||
if self.keepalive_timer.is_none() {
|
if self.keepalive_timer.is_none() {
|
||||||
trace!("Start keep-alive timer");
|
trace!("Start keep-alive timer");
|
||||||
let mut to = Timeout::new(
|
let mut to = Timeout::new(
|
||||||
Duration::new(keep_alive as u64, 0),
|
Duration::new(keep_alive, 0),
|
||||||
Arbiter::handle()).unwrap();
|
Arbiter::handle()).unwrap();
|
||||||
// register timeout
|
// register timeout
|
||||||
let _ = to.poll();
|
let _ = to.poll();
|
||||||
|
@ -159,7 +159,7 @@ impl<T, H> Http2<T, H>
|
|||||||
if keep_alive > 0 && self.keepalive_timer.is_none() {
|
if keep_alive > 0 && self.keepalive_timer.is_none() {
|
||||||
trace!("Start keep-alive timer");
|
trace!("Start keep-alive timer");
|
||||||
let mut timeout = Timeout::new(
|
let mut timeout = Timeout::new(
|
||||||
Duration::new(keep_alive as u64, 0),
|
Duration::new(keep_alive, 0),
|
||||||
Arbiter::handle()).unwrap();
|
Arbiter::handle()).unwrap();
|
||||||
// register timeout
|
// register timeout
|
||||||
let _ = timeout.poll();
|
let _ = timeout.poll();
|
||||||
|
@ -309,7 +309,7 @@ impl HttpResponseBuilder {
|
|||||||
|
|
||||||
/// Enables automatic chunked transfer encoding
|
/// Enables automatic chunked transfer encoding
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn enable_chunked(&mut self) -> &mut Self {
|
pub fn chunked(&mut self) -> &mut Self {
|
||||||
if let Some(parts) = parts(&mut self.response, &self.err) {
|
if let Some(parts) = parts(&mut self.response, &self.err) {
|
||||||
parts.chunked = true;
|
parts.chunked = true;
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,7 @@ pub mod dev {
|
|||||||
//! use actix_web::dev::*;
|
//! use actix_web::dev::*;
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
pub use body::BodyStream;
|
||||||
pub use info::ConnectionInfo;
|
pub use info::ConnectionInfo;
|
||||||
pub use handler::Handler;
|
pub use handler::Handler;
|
||||||
pub use router::{Router, Pattern};
|
pub use router::{Router, Pattern};
|
||||||
|
@ -7,6 +7,7 @@ use bytes::{Bytes, BytesMut};
|
|||||||
use futures::{Async, Poll, Stream};
|
use futures::{Async, Poll, Stream};
|
||||||
use futures::task::{Task, current as current_task};
|
use futures::task::{Task, current as current_task};
|
||||||
|
|
||||||
|
use body::BodyStream;
|
||||||
use actix::ResponseType;
|
use actix::ResponseType;
|
||||||
use error::PayloadError;
|
use error::PayloadError;
|
||||||
|
|
||||||
@ -121,6 +122,11 @@ impl Payload {
|
|||||||
pub fn set_buffer_size(&self, size: usize) {
|
pub fn set_buffer_size(&self, size: usize) {
|
||||||
self.inner.borrow_mut().set_buffer_size(size)
|
self.inner.borrow_mut().set_buffer_size(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert payload into BodyStream
|
||||||
|
pub fn stream(self) -> BodyStream {
|
||||||
|
Box::new(self.map(|item| item.0).map_err(|e| e.into()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream for Payload {
|
impl Stream for Payload {
|
||||||
|
@ -94,7 +94,7 @@ pub struct HttpServer<T, A, H, U>
|
|||||||
io: PhantomData<T>,
|
io: PhantomData<T>,
|
||||||
addr: PhantomData<A>,
|
addr: PhantomData<A>,
|
||||||
threads: usize,
|
threads: usize,
|
||||||
keep_alive: Option<u16>,
|
keep_alive: Option<u64>,
|
||||||
factory: Arc<Fn() -> U + Send + Sync>,
|
factory: Arc<Fn() -> U + Send + Sync>,
|
||||||
workers: Vec<SyncAddress<Worker<H>>>,
|
workers: Vec<SyncAddress<Worker<H>>>,
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ impl<T, A, H, U, V> HttpServer<T, A, H, U>
|
|||||||
/// - `Some(0)` - disable
|
/// - `Some(0)` - disable
|
||||||
///
|
///
|
||||||
/// - `None` - use `SO_KEEPALIVE` socket option
|
/// - `None` - use `SO_KEEPALIVE` socket option
|
||||||
pub fn keep_alive(mut self, val: Option<u16>) -> Self {
|
pub fn keep_alive(mut self, val: Option<u64>) -> Self {
|
||||||
self.keep_alive = val;
|
self.keep_alive = val;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -240,7 +240,7 @@ impl<T, A, H, U, V> HttpServer<T, A, H, U>
|
|||||||
let (tx, rx) = mpsc::unbounded::<IoStream<Socket>>();
|
let (tx, rx) = mpsc::unbounded::<IoStream<Socket>>();
|
||||||
|
|
||||||
let h = handler.clone();
|
let h = handler.clone();
|
||||||
let ka = self.keep_alive.clone();
|
let ka = self.keep_alive;
|
||||||
let factory = Arc::clone(&self.factory);
|
let factory = Arc::clone(&self.factory);
|
||||||
let addr = Arbiter::start(move |ctx: &mut Context<_>| {
|
let addr = Arbiter::start(move |ctx: &mut Context<_>| {
|
||||||
let mut apps: Vec<_> = (*factory)()
|
let mut apps: Vec<_> = (*factory)()
|
||||||
@ -396,7 +396,7 @@ impl<T, A, H, U> Handler<IoStream<T>, io::Error> for HttpServer<T, A, H, U>
|
|||||||
-> Response<Self, IoStream<T>>
|
-> Response<Self, IoStream<T>>
|
||||||
{
|
{
|
||||||
Arbiter::handle().spawn(
|
Arbiter::handle().spawn(
|
||||||
HttpChannel::new(Rc::clone(&self.h.as_ref().unwrap()), msg.io, msg.peer, msg.http2));
|
HttpChannel::new(Rc::clone(self.h.as_ref().unwrap()), msg.io, msg.peer, msg.http2));
|
||||||
Self::empty()
|
Self::empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,21 +412,21 @@ struct Worker<H> {
|
|||||||
|
|
||||||
pub(crate) struct WorkerSettings<H> {
|
pub(crate) struct WorkerSettings<H> {
|
||||||
h: Vec<H>,
|
h: Vec<H>,
|
||||||
keep_alive: Option<u16>,
|
keep_alive: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H> WorkerSettings<H> {
|
impl<H> WorkerSettings<H> {
|
||||||
pub fn handlers(&self) -> &Vec<H> {
|
pub fn handlers(&self) -> &Vec<H> {
|
||||||
&self.h
|
&self.h
|
||||||
}
|
}
|
||||||
pub fn keep_alive(&self) -> Option<u16> {
|
pub fn keep_alive(&self) -> Option<u64> {
|
||||||
self.keep_alive
|
self.keep_alive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: 'static> Worker<H> {
|
impl<H: 'static> Worker<H> {
|
||||||
|
|
||||||
fn new(h: Vec<H>, handler: StreamHandlerType, keep_alive: Option<u16>) -> Worker<H> {
|
fn new(h: Vec<H>, handler: StreamHandlerType, keep_alive: Option<u64>) -> Worker<H> {
|
||||||
Worker {
|
Worker {
|
||||||
h: Rc::new(WorkerSettings{h: h, keep_alive: keep_alive}),
|
h: Rc::new(WorkerSettings{h: h, keep_alive: keep_alive}),
|
||||||
handler: handler,
|
handler: handler,
|
||||||
@ -456,11 +456,11 @@ impl<H> Handler<IoStream<Socket>> for Worker<H>
|
|||||||
fn handle(&mut self, msg: IoStream<Socket>, _: &mut Context<Self>)
|
fn handle(&mut self, msg: IoStream<Socket>, _: &mut Context<Self>)
|
||||||
-> Response<Self, IoStream<Socket>>
|
-> Response<Self, IoStream<Socket>>
|
||||||
{
|
{
|
||||||
if let None = self.h.keep_alive {
|
if self.h.keep_alive.is_none() &&
|
||||||
if msg.io.set_keepalive(Some(Duration::new(75, 0))).is_err() {
|
msg.io.set_keepalive(Some(Duration::new(75, 0))).is_err()
|
||||||
|
{
|
||||||
error!("Can not set socket keep-alive option");
|
error!("Can not set socket keep-alive option");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.handler.handle(Rc::clone(&self.h), msg);
|
self.handler.handle(Rc::clone(&self.h), msg);
|
||||||
Self::empty()
|
Self::empty()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user