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