mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-28 01:52:57 +01:00
Tweaks to the Handler chapter.
This commit is contained in:
parent
7f0de705a3
commit
961edfd21a
@ -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.
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user