1
0
mirror of https://github.com/actix/actix-website synced 2025-01-22 16:15:56 +01:00

Middleware section is done-ish.

This commit is contained in:
Cameron Dershem 2019-06-26 02:59:20 -04:00
parent 1c3697197d
commit eff4edb6fa
6 changed files with 122 additions and 102 deletions

View File

@ -6,9 +6,9 @@ weight: 220
# Middleware # Middleware
Actix's middleware system allows us to add additional behavior to request/response processing. Actix-web's middleware system allows us to add additional behavior to request/response
Middleware can hook into an incoming request process, enabling us to modify requests processing. Middleware can hook into an incoming request process, enabling us to modify
as well as halt request processing to return a response early. requests as well as halt request processing to return a response early.
Middleware can also hook into response processing. Middleware can also hook into response processing.
@ -19,31 +19,32 @@ Typically, middleware is involved in the following actions:
* Modify application state * Modify application state
* Access external services (redis, logging, sessions) * Access external services (redis, logging, sessions)
Middleware is registered for each application and executed in same order as registration. Middleware is registered for each `App`, `scope`, or `Resource` and executed in opposite
In general, a *middleware* is a type that implements the [*Service trait*][servicetrait] and order as registration. In general, a *middleware* is a type that implements the
[*Transform trait*][transformtrait]. Each method in the traits has a default [*Service trait*][servicetrait] and [*Transform trait*][transformtrait]. Each method in
implementation. Each method can return a result immediately or a *future* object. the traits has a default implementation. Each method can return a result immediately
or a *future* object.
The following demonstrates creating a simple middleware: The following demonstrates creating a simple middleware:
{{< include-example example="middleware" file="main.rs" section="main" >}} {{< include-example example="middleware" file="main.rs" section="simple" >}}
> Actix provides several useful middlewares, such as *logging*, *user sessions*, etc. > Actix-web provides several useful middlewares, such as *logging*, *user sessions*,
> *compress*, etc.
# Logging # Logging
Logging is implemented as a middleware. Logging is implemented as a middleware. It is common to register a logging middleware
It is common to register a logging middleware as the first middleware for the application. as the first middleware for the application. Logging middleware must be registered for
Logging middleware must be registered for each application. each application.
The `Logger` middleware uses the standard log crate to log information. You should enable logger The `Logger` middleware uses the standard log crate to log information. You should enable logger
for *actix_web* package to see access log ([env_logger][envlogger] for *actix_web* package to see access log ([env_logger][envlogger] or similar).
or similar).
## Usage ## Usage
Create `Logger` middleware with the specified `format`. Create `Logger` middleware with the specified `format`. Default `Logger` can be created
Default `Logger` can be created with `default` method, it uses the default format: with `default` method, it uses the default format:
```ignore ```ignore
%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T %a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
@ -60,29 +61,18 @@ INFO:actix_web::middleware::logger: 127.0.0.1:59947 [02/Dec/2017:00:22:40 -0800]
## Format ## Format
`%%` The percent sign - `%%` The percent sign
- `%a` Remote IP-address (IP-address of proxy if using reverse proxy)
`%a` Remote IP-address (IP-address of proxy if using reverse proxy) - `%t` Time when the request was started to process
- `%P` The process ID of the child that serviced the request
`%t` Time when the request was started to process - `%r` First line of request
- `%s` Response status code
`%P` The process ID of the child that serviced the request - `%b` Size of response in bytes, including HTTP headers
- `%T` Time taken to serve the request, in seconds with floating fraction in .06f format
`%r` First line of request - `%D` Time taken to serve the request, in milliseconds
- `%{FOO}i` request.headers['FOO']
`%s` Response status code - `%{FOO}o` response.headers['FOO']
- `%{FOO}e` os.environ['FOO']
`%b` Size of response in bytes, including HTTP headers
`%T` Time taken to serve the request, in seconds with floating fraction in .06f format
`%D` Time taken to serve the request, in milliseconds
`%{FOO}i` request.headers['FOO']
`%{FOO}o` response.headers['FOO']
`%{FOO}e` os.environ['FOO']
## Default headers ## Default headers
@ -94,8 +84,9 @@ a specified header.
## User sessions ## User sessions
Actix provides a general solution for session management. The [**actix-session**][actixsession] Actix-web provides a general solution for session management. The
middleware can be used with different backend types to store session data in different backends. [**actix-session**][actixsession] middleware can be used with different backend types
to store session data in different backends.
> By default, only cookie session backend is implemented. Other backend implementations > By default, only cookie session backend is implemented. Other backend implementations
> can be added. > can be added.
@ -115,8 +106,8 @@ The constructors take a key as an argument. This is the private key for cookie s
when this value is changed, all session data is lost. when this value is changed, all session data is lost.
In general, you create a `SessionStorage` middleware and initialize it with specific In general, you create a `SessionStorage` middleware and initialize it with specific
backend implementation, such as a `CookieSession`. To access session data, backend implementation, such as a `CookieSession`. To access session data the
[*HttpRequest::session()*][requestsession] must be used. This method returns a [`Session`][requestsession] extractor must be used. This method returns a
[*Session*][sessionobj] object, which allows us to get or set session data. [*Session*][sessionobj] object, which allows us to get or set session data.
{{< include-example example="middleware" file="user_sessions.rs" section="user-session" >}} {{< include-example example="middleware" file="user_sessions.rs" section="user-session" >}}
@ -132,10 +123,10 @@ into a response.
{{< include-example example="middleware" file="errorhandler.rs" section="error-handler" >}} {{< include-example example="middleware" file="errorhandler.rs" section="error-handler" >}}
[sessionobj]: ../../actix-web/actix_web/middleware/session/struct.Session.html [sessionobj]: https://docs.rs/actix-session/0.1.1/actix_session/struct.Session.html
[requestsession]: ../../actix-web/actix_web/middleware/session/trait.RequestSession.html#tymethod.session [requestsession]: https://docs.rs/actix-session/0.1.1/actix_session/struct.Session.html
[cookiesession]: ../../actix-web/actix_web/middleware/session/struct.CookieSessionBackend.html [cookiesession]: https://docs.rs/actix-session/0.1.1/actix_session/struct.CookieSession.html
[actixsession]: https://docs.rs/actix-session/0.1.1/actix_session/ [actixsession]: https://docs.rs/actix-session/0.1.1/actix_session/
[envlogger]: https://docs.rs/env_logger/*/env_logger/ [envlogger]: https://docs.rs/env_logger/*/env_logger/
[servicetrait]: ../../actix-web/actix_web/dev/trait.Service.html [servicetrait]: https://docs.rs/actix-web/1.0.2/actix_web/dev/trait.Service.html
[transformtrait]: ../../actix-web/actix_web/dev/trait.Transform.html [transformtrait]: https://docs.rs/actix-web/1.0.2/actix_web/dev/trait.Transform.html

View File

@ -1,16 +1,24 @@
// <default-headers> // <default-headers>
use actix_web::{http, middleware, web, App, HttpResponse}; use actix_web::{http, middleware, HttpResponse};
pub fn main() { pub fn main() {
App::new() use actix_web::{web, App, HttpServer};
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.service( HttpServer::new(|| {
web::resource("/test") App::new()
.route(web::get().to(|| HttpResponse::Ok())) .wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.route( .service(
web::method(http::Method::HEAD) web::resource("/test")
.to(|| HttpResponse::MethodNotAllowed()), .route(web::get().to(|| HttpResponse::Ok()))
), .route(
); web::method(http::Method::HEAD)
.to(|| HttpResponse::MethodNotAllowed()),
),
)
})
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
} }
// </default-headers> // </default-headers>

View File

@ -1,6 +1,6 @@
// <error-handler> // <error-handler>
use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers}; use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
use actix_web::{dev, http, web, App, HttpResponse, Result}; use actix_web::{dev, http, HttpResponse, Result};
fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> { fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
res.response_mut().headers_mut().insert( res.response_mut().headers_mut().insert(
@ -11,15 +11,23 @@ fn render_500<B>(mut res: dev::ServiceResponse<B>) -> Result<ErrorHandlerRespons
} }
pub fn main() { pub fn main() {
App::new() use actix_web::{web, App, HttpServer};
.wrap(
ErrorHandlers::new() HttpServer::new(|| {
.handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500), App::new()
) .wrap(
.service( ErrorHandlers::new()
web::resource("/test") .handler(http::StatusCode::INTERNAL_SERVER_ERROR, render_500),
.route(web::get().to(|| HttpResponse::Ok())) )
.route(web::head().to(|| HttpResponse::MethodNotAllowed())), .service(
); web::resource("/test")
.route(web::get().to(|| HttpResponse::Ok()))
.route(web::head().to(|| HttpResponse::MethodNotAllowed())),
)
})
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
} }
// </error-handler> // </error-handler>

View File

@ -1,14 +1,21 @@
// <logger> // <logger>
use actix_web::middleware::Logger; use actix_web::middleware::Logger;
use actix_web::App;
use env_logger; use env_logger;
pub fn main() { pub fn main() {
use actix_web::{App, HttpServer};
std::env::set_var("RUST_LOG", "actix_web=info"); std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init(); env_logger::init();
App::new() HttpServer::new(|| {
.wrap(Logger::default()) App::new()
.wrap(Logger::new("%a %{User-Agent}i")); .wrap(Logger::default())
.wrap(Logger::new("%a %{User-Agent}i"))
})
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
} }
// </logger> // </logger>

View File

@ -2,9 +2,10 @@ pub mod default_headers;
pub mod errorhandler; pub mod errorhandler;
pub mod logger; pub mod logger;
pub mod user_sessions; pub mod user_sessions;
// <main>
// <simple>
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, web, App, Error}; use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error};
use futures::future::{ok, FutureResult}; use futures::future::{ok, FutureResult};
use futures::{Future, Poll}; use futures::{Future, Poll};
@ -63,10 +64,19 @@ where
})) }))
} }
} }
// </main> // </simple>
fn main() { fn main() {
App::new().wrap(SayHi).service( use actix_web::{web, App, HttpServer};
web::resource("/")
.to(|| "Hello, middleware! Check the console where the server is run."), HttpServer::new(|| {
); App::new().wrap(SayHi).service(
web::resource("/")
.to(|| "Hello, middleware! Check the console where the server is run."),
)
})
.bind("127.0.0.1:8088")
.unwrap()
.run()
.unwrap();
} }

View File

@ -1,37 +1,33 @@
// <user-session> // <user-session>
use actix_session::{CookieSession, Session}; use actix_session::{CookieSession, Session};
use actix_web::{middleware::Logger, web, App, HttpRequest, HttpServer, Result}; use actix_web::{web, App, Error, HttpResponse, HttpServer};
/// simple index handler with session pub fn index(session: Session) -> Result<HttpResponse, Error> {
fn index(session: Session, req: HttpRequest) -> Result<&'static str> { // access session data
println!("{:?}", req);
// RequestSession trait is used for session access
let mut counter = 1;
if let Some(count) = session.get::<i32>("counter")? { if let Some(count) = session.get::<i32>("counter")? {
println!("SESSION value: {}", count); session.set("counter", count + 1)?;
counter = count + 1;
session.set("counter", counter)?;
} else { } else {
session.set("counter", counter)?; session.set("counter", 1)?;
} }
Ok("welcome!") Ok(HttpResponse::Ok().body(format!(
"Count is {:?}!",
session.get::<i32>("counter")?.unwrap()
)))
} }
pub fn main() -> std::io::Result<()> { pub fn main() {
std::env::set_var("RUST_LOG", "actix_web=info");
env_logger::init();
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
// enable logger .wrap(
.wrap(Logger::default()) CookieSession::signed(&[0; 32]) // <- create cookie based session middleware
// cookie session middleware .secure(false),
.wrap(CookieSession::signed(&[0; 32]).secure(false)) )
.service(web::resource("/").to(index)) .service(web::resource("/").to(index))
}) })
.bind("127.0.0.1:8080")? .bind("127.0.0.1:8088")
.unwrap()
.run() .run()
.unwrap();
} }
// </user-session> // </user-session>