1
0
mirror of https://github.com/actix/examples synced 2024-11-27 16:02:57 +01:00

Working middleware using extensions_mut (#402)

Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
Eric 2021-10-06 23:04:19 -04:00 committed by GitHub
parent 0c4ab86a9a
commit 817c7e1150
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 171 additions and 2 deletions

8
Cargo.lock generated
View File

@ -3760,6 +3760,14 @@ dependencies = [
"pin-project 0.4.28", "pin-project 0.4.28",
] ]
[[package]]
name = "middleware-ext-mut"
version = "0.1.0"
dependencies = [
"actix-web 3.3.2",
"env_logger 0.9.0",
]
[[package]] [[package]]
name = "mime" name = "mime"
version = "0.3.16" version = "0.3.16"

View File

@ -7,6 +7,7 @@ members = [
"basics/http-proxy", "basics/http-proxy",
"basics/json-validation", "basics/json-validation",
"basics/middleware", "basics/middleware",
"basics/middleware-ext-mut",
"basics/nested-routing", "basics/nested-routing",
"basics/run-in-thread", "basics/run-in-thread",
"basics/shutdown-server", "basics/shutdown-server",

View File

@ -0,0 +1,10 @@
[package]
name = "middleware-ext-mut"
version = "0.1.0"
authors = ["Eric McCarthy <ericmccarthy7@gmail.com>"]
edition = "2018"
[dependencies]
actix-web = "3"
env_logger = "0.9"

View File

@ -0,0 +1,18 @@
# middleware examples
This example showcases a middleware that adds and retreives request-local data. See also the [Middleware guide](https://actix.rs/docs/middleware/).
## Usage
```bash
cd basics/middleware-ext-mut
cargo run
# Started http server: 127.0.0.1:8080
```
Look in `src/add_msg.rs` to see how it works.
## Routes
- [GET /on](http://localhost:8080/on) - `200 OK` with "hello from middleware" body and console log showing the request passed through the middleware
- [GET /off](http://localhost:8080/off) - `500 Internal Server Error` with "no message found" body and console log showing the request passed through the middleware

View File

@ -0,0 +1,97 @@
use std::{
future::{ready, Future, Ready},
pin::Pin,
task::{Context, Poll},
};
use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
use actix_web::Error;
#[derive(Debug, Clone)]
pub struct Msg(pub String);
#[doc(hidden)]
pub struct AddMsgService<S> {
service: S,
enabled: bool,
}
impl<S, B> Service for AddMsgService<S>
where
S: Service<
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = actix_web::Error,
>,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Error>>>>;
fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(ctx)
}
fn call(&mut self, req: Self::Request) -> Self::Future {
println!("request is passing through the AddMsg middleware");
// get mut HttpRequest from ServiceRequest
let (request, pl) = req.into_parts();
if self.enabled {
// insert data into extensions if enabled
request
.extensions_mut()
.insert(Msg("Hello from Middleware!".to_owned()));
}
// construct a new service response
match ServiceRequest::from_parts(request, pl) {
Ok(req) => Box::pin(self.service.call(req)),
Err(_) => Box::pin(ready(Err(Error::from(())))),
}
}
}
#[derive(Clone, Debug)]
pub struct AddMsg {
enabled: bool,
}
impl AddMsg {
pub fn enabled() -> Self {
Self { enabled: true }
}
pub fn disabled() -> Self {
Self { enabled: false }
}
}
impl<S, B> Transform<S> for AddMsg
where
S: Service<
Request = ServiceRequest,
Response = ServiceResponse<B>,
Error = actix_web::Error,
>,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
type Transform = AddMsgService<S>;
type InitError = ();
fn new_transform(&self, service: S) -> Self::Future {
ready(Ok(AddMsgService {
service,
enabled: self.enabled,
}))
}
}

View File

@ -0,0 +1,36 @@
use std::{env, io};
use actix_web::{
middleware,
web::{self, ReqData},
App, HttpResponse, HttpServer,
};
mod add_msg;
use crate::add_msg::{AddMsg, Msg};
// wrap route in our middleware factory
async fn index(msg: Option<ReqData<Msg>>) -> HttpResponse {
if let Some(msg_data) = msg {
let Msg(message) = msg_data.into_inner();
HttpResponse::Ok().body(message)
} else {
HttpResponse::InternalServerError().body("No message found.")
}
}
#[actix_web::main]
async fn main() -> io::Result<()> {
env::set_var("RUST_LOG", "info");
env_logger::init();
HttpServer::new(|| {
App::new()
.wrap(middleware::Logger::default())
.service(web::resource("/on").wrap(AddMsg::enabled()).to(index))
.service(web::resource("/off").wrap(AddMsg::disabled()).to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}

View File

@ -10,8 +10,7 @@ cargo run
# Started http server: 127.0.0.1:8080 # Started http server: 127.0.0.1:8080
``` ```
Look in `src/main.rs` and comment the different middlewares in/out to see how Look in `src/main.rs` and comment the different middlewares in/out to see how they function.
they function.
## Middlewares ## Middlewares