1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 07:53:00 +01:00

Tweaks to the Handler chapter.

This commit is contained in:
memoryruins 2018-04-05 21:30:52 -04:00
parent 7f0de705a3
commit 961edfd21a

View File

@ -1,17 +1,18 @@
# Handler
A request handler can be any object that implements
[*Handler trait*](../actix_web/dev/trait.Handler.html).
Request handling happens in two stages. First the handler object is called.
Handler can return any object that implements
[*Responder trait*](../actix_web/trait.Responder.html#foreign-impls).
Then `respond_to()` is called on the returned object. And finally
result of the `respond_to()` call is converted to a `Reply` object.
[`Handler` trait](../actix_web/dev/trait.Handler.html).
Request handling happens in two stages. First the handler object is called,
returning any object that implements the
[`Responder` trait](../actix_web/trait.Responder.html#foreign-impls).
Then, `respond_to()` is called on the returned object, converting itself to a `Reply` or `Error`.
By default actix provides `Responder` implementations for some standard types,
like `&'static str`, `String`, etc.
For a complete list of implementations, check
[*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
such as `&'static str`, `String`, etc.
> For a complete list of implementations, check
> [*Responder documentation*](../actix_web/trait.Responder.html#foreign-impls).
Examples of valid handlers:
@ -39,15 +40,16 @@ fn index(req: HttpRequest) -> Box<Future<Item=HttpResponse, Error=Error>> {
}
```
Some notes on shared application state and handler state. If you noticed
*Handler* trait is generic over *S*, which defines application state type. So
application state is accessible from handler with the `HttpRequest::state()` method.
But state is accessible as a read-only reference - if you need mutable access to state
you have to implement it yourself. On other hand, handler can mutably access its own state
as the `handle` method takes a mutable reference to *self*. Beware, actix creates multiple copies
of application state and handlers, unique for each thread, so if you run your
application in several threads, actix will create the same amount as number of threads
of application state objects and handler objects.
*Handler* trait is generic over *S*, which defines the application state's type.
Application state is accessible from the handler with the `HttpRequest::state()` method;
however, state is accessible as a read-only reference. If you need mutable access to state,
it must be implemented.
> **Note**: Alternatively, the handler can mutably access its own state because the `handle` method takes
> mutable reference to *self*. **Beware**, actix creates multiple copies
> of the application state and the handlers, unique for each thread. If you run your
> application in several threads, actix will create the same amount as number of threads
> of application state objects and handler objects.
Here is an example of a handler that stores the number of processed requests:
@ -69,8 +71,8 @@ impl<S> Handler<S> for MyHandler {
# fn main() {}
```
This handler will work, but `self.0` will be different depending on the number of threads and
number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`
Although this handler will work, `self.0` will be different depending on the number of threads and
number of requests processed per thread. A proper implementation would use `Arc` and `AtomicUsize`.
```rust
# extern crate actix;
@ -111,14 +113,15 @@ fn main() {
}
```
Be careful with synchronization primitives like *Mutex* or *RwLock*. Actix web framework
handles requests asynchronously; by blocking thread execution all concurrent
request handling processes would block. If you need to share or update some state
from multiple threads consider using the [actix](https://actix.github.io/actix/actix/) actor system.
> Be careful with synchronization primitives like `Mutex` or `RwLock`. Actix web framework
> handles requests asynchronously. By blocking thread execution, all concurrent
> request handling processes would block. If you need to share or update some state
> from multiple threads, consider using the [actix](https://actix.github.io/actix/actix/) actor system.
## Response with custom type
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
To return a custom type directly from a handler function, the type needs to implement the `Responder` trait.
Let's create a response for a custom type that serializes to an `application/json` response:
```rust
@ -171,10 +174,10 @@ fn main() {
## Async handlers
There are two different types of async handlers.
There are two different types of async handlers. Response objects can be generated asynchronously
or more precisely, any type that implements the [*Responder*](../actix_web/trait.Responder.html) trait.
Response objects can be generated asynchronously or more precisely, any type
that implements the [*Responder*](../actix_web/trait.Responder.html) trait. In this case the handler must return a `Future` object that resolves to the *Responder* type, i.e:
In this case, the handler must return a `Future` object that resolves to the *Responder* type, i.e:
```rust
# extern crate actix_web;
@ -205,8 +208,8 @@ fn main() {
}
```
Or the response body can be generated asynchronously. In this case body
must implement stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
Or the response body can be generated asynchronously. In this case, body
must implement the stream trait `Stream<Item=Bytes, Error=Error>`, i.e:
```rust
# extern crate actix_web;
@ -233,7 +236,7 @@ fn main() {
Both methods can be combined. (i.e Async response with streaming body)
It is possible to return a `Result` where the `Result::Item` type can be `Future`.
In this example the `index` handler can return an error immediately or return a
In this example, the `index` handler can return an error immediately or return a
future that resolves to a `HttpResponse`.
```rust
@ -265,11 +268,11 @@ fn index(req: HttpRequest) -> Result<Box<Future<Item=HttpResponse, Error=Error>>
## Different return types (Either)
Sometimes you need to return different types of responses. For example
you can do error check and return error and return async response otherwise.
Or any result that requires two different types.
For this case the [*Either*](../actix_web/enum.Either.html) type can be used.
*Either* allows combining two different responder types into a single type.
Sometimes, you need to return different types of responses. For example,
you can error check and return errors, return async responses, or any result that requires two different types.
For this case, the [`Either`](../actix_web/enum.Either.html) type can be used.
`Either` allows combining two different responder types into a single type.
```rust
# extern crate actix_web;