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

Add middleware example for reading the Request body

This commit is contained in:
Sven-Hendrik Haase 2019-09-11 15:12:08 +02:00
parent f232b6c684
commit 0f692a3bfb
4 changed files with 75 additions and 2 deletions

View File

@ -9,4 +9,5 @@ workspace = ".."
actix-service = "0.4.1" actix-service = "0.4.1"
actix-web = "1.0.0" actix-web = "1.0.0"
futures = "0.1.25" futures = "0.1.25"
env_logger = "0.6" env_logger = "0.6"
bytes = "0.4"

View File

@ -8,4 +8,3 @@ cargo run
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.

View File

@ -3,6 +3,8 @@ use actix_web::{web, App, HttpServer};
#[allow(dead_code)] #[allow(dead_code)]
mod redirect; mod redirect;
#[allow(dead_code)] #[allow(dead_code)]
mod read_body;
#[allow(dead_code)]
mod simple; mod simple;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
@ -12,6 +14,7 @@ fn main() -> std::io::Result<()> {
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
.wrap(redirect::CheckLogin) .wrap(redirect::CheckLogin)
.wrap(read_body::Logging)
.wrap(simple::SayHi) .wrap(simple::SayHi)
.service(web::resource("/login").to(|| { .service(web::resource("/login").to(|| {
"You are on /login. Go to src/redirect.rs to change this behavior." "You are on /login. Go to src/redirect.rs to change this behavior."

View File

@ -0,0 +1,70 @@
use actix_service::{Service, Transform};
use actix_web::error::PayloadError;
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error, HttpMessage};
use bytes::BytesMut;
use futures::future::{ok, FutureResult};
use futures::stream::Stream;
use futures::{Future, Poll};
use std::cell::RefCell;
use std::rc::Rc;
pub struct Logging;
impl<S: 'static, B> Transform<S> for Logging
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = LoggingMiddleware<S>;
type Future = FutureResult<Self::Transform, Self::InitError>;
fn new_transform(&self, service: S) -> Self::Future {
ok(LoggingMiddleware {
service: Rc::new(RefCell::new(service)),
})
}
}
pub struct LoggingMiddleware<S> {
// This is special: We need this to avoid lifetime issues.
service: Rc<RefCell<S>>,
}
impl<S, B> Service for LoggingMiddleware<S>
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>
+ 'static,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error>>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.service.poll_ready()
}
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
let mut svc = self.service.clone();
Box::new(
req.take_payload()
.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.map_err(|e| e.into())
.and_then(move |bytes| {
println!("request body: {:?}", bytes);
svc.call(req).and_then(|res| Ok(res))
}),
)
}
}