1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-30 18:34:36 +01:00

more info for middleware guide

This commit is contained in:
Nikolay Kim 2017-12-26 07:58:21 -08:00
parent ffb5742b71
commit b61a07a320
2 changed files with 67 additions and 10 deletions

View File

@ -1,8 +1,68 @@
# Middlewares # Middlewares
Actix middlewares system allows to add additional behaviour to request/response processing.
Middleware can hook into incomnig request process and modify request or halt request
processing and return response early. Also it can hook into response processing.
Typically middlewares involves in following actions:
* Pre-process the Request
* Post-process a Response
* Modify application state
* Access external services (redis, logging, sessions)
Middlewares are registered for each application and get executed in same order as
registraton order. In general, *middleware* is a type that implements
[*Middleware trait*](../actix_web/middlewares/trait.Middleware.html). Each method
in this trait has default implementation. Each method can return result immidietly
or *future* object.
Here is example of simple middleware that adds request and response headers:
```rust
# extern crate http;
# extern crate actix_web;
use http::{header, HttpTryFrom};
use actix_web::*;
use actix_web::middlewares::{Middleware, Started, Response};
struct Headers; // <- Our middleware
/// Middleware implementation, middlewares are generic over application state,
/// so you can access state with `HttpRequest::state()` method.
impl<S> Middleware<S> for Headers {
/// Method is called when request is ready. It may return
/// future, which should resolve before next middleware get called.
fn start(&self, req: &mut HttpRequest<S>) -> Started {
req.headers_mut().insert(
header::CONTENT_TYPE, header::HeaderValue::from_static("text/plain"));
Started::Done
}
/// Method is called when handler returns response,
/// but before sending http message to peer.
fn response(&self, req: &mut HttpRequest<S>, mut resp: HttpResponse) -> Response {
resp.headers_mut().insert(
header::HeaderName::try_from("X-VERSION").unwrap(),
header::HeaderValue::from_static("0.2"));
Response::Done(resp)
}
}
fn main() {
Application::new()
.middleware(Headers) // <- Register middleware, this method could be called multiple times
.resource("/", |r| r.h(httpcodes::HTTPOk));
}
```
Active provides several useful middlewares, like *logging*, *user sessions*, etc.
## Logging ## Logging
Logging is implemented as middleware. Middlewares get executed in same order as registraton order. Logging is implemented as middleware.
It is common to register logging middleware as first middleware for application. It is common to register logging middleware as first middleware for application.
Logging middleware has to be registered for each application. Logging middleware has to be registered for each application.

View File

@ -8,7 +8,7 @@ Technically sync actors are worker style actors, multiple of them
can be run in parallel and process messages from same queue (sync actors work in mpmc mode). can be run in parallel and process messages from same queue (sync actors work in mpmc mode).
Let's create simple db api that can insert new user row into sqlite table. Let's create simple db api that can insert new user row into sqlite table.
We need to define sync actor and connection that this actor will use. Same approach We have to define sync actor and connection that this actor will use. Same approach
could used for other databases. could used for other databases.
```rust,ignore ```rust,ignore
@ -24,14 +24,11 @@ impl Actor for DbExecutor {
This is definition of our actor. Now we need to define *create user* message and response. This is definition of our actor. Now we need to define *create user* message and response.
```rust,ignore ```rust,ignore
#[derive(Message)]
#[rtype(User, Error)]
struct CreateUser { struct CreateUser {
name: String, name: String,
} }
impl ResponseType for CreateUser {
type Item = models::User;
type Error = Error;
}
``` ```
We can send `CreateUser` message to `DbExecutor` actor, and as result we can get We can send `CreateUser` message to `DbExecutor` actor, and as result we can get
@ -68,11 +65,11 @@ impl Handler<CreateUser> for DbExecutor {
``` ```
That is it. Now we can use *DbExecutor* actor from any http handler or middleware. That is it. Now we can use *DbExecutor* actor from any http handler or middleware.
All we need is to start *DbExecutor* actors and store address in state where http handler All we need is to start *DbExecutor* actors and store address in a state where http handler
can access it. can access it.
```rust,ignore ```rust,ignore
/// This is state where we sill store *DbExecutor* address. /// This is state where we store *DbExecutor* address.
struct State { struct State {
db: SyncAddress<DbExecutor>, db: SyncAddress<DbExecutor>,
} }
@ -97,7 +94,7 @@ fn main() {
} }
``` ```
And finally we can use this state in handler function. We get message response And finally we can use this state in a requst handler. We get message response
asynchronously, so handler needs to return future object, also `Route::a()` needs to be asynchronously, so handler needs to return future object, also `Route::a()` needs to be
used for async handler registration. used for async handler registration.