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

Add middleware to log the response body

This commit is contained in:
Sven-Hendrik Haase 2019-09-18 04:37:35 +02:00
parent fb6d5254bf
commit 56859e14d2
5 changed files with 81 additions and 4 deletions

View File

@ -1,7 +1,7 @@
[package]
name = "middleware-example"
version = "0.1.0"
authors = ["Gorm Casper <gcasper@gmail.com>"]
authors = ["Gorm Casper <gcasper@gmail.com>", "Sven-Hendrik Haase <svenstaro@gmail.com>"]
edition = "2018"
workspace = ".."

View File

@ -19,10 +19,14 @@ they function.
A middleware implementing a request guard which sketches a rough approximation of what a login could look like.
### read_body::Logging
### read_request_body::Logging
A middleware demonstrating how to read out the incoming request body.
### read_response_body::Logging
A middleware demonstrating how to read out the outgoing response body.
### simple::SayHi
A minimal middleware demonstrating the sequence of operations in an actix middleware.

View File

@ -5,7 +5,9 @@ use futures::future::Future;
#[allow(dead_code)]
mod redirect;
#[allow(dead_code)]
mod read_body;
mod read_request_body;
#[allow(dead_code)]
mod read_response_body;
#[allow(dead_code)]
mod simple;
@ -16,7 +18,8 @@ fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.wrap(redirect::CheckLogin)
.wrap(read_body::Logging)
.wrap(read_request_body::Logging)
.wrap(read_response_body::Logging)
.wrap(simple::SayHi)
.wrap_fn(|req, srv| {
println!("Hi from start. You requested: {}", req.path());

View File

@ -0,0 +1,70 @@
use actix_service::{Service, Transform};
use actix_web::body::{Body, MessageBody, ResponseBody};
use actix_web::error::PayloadError;
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error};
use bytes::BytesMut;
use futures::future::{ok, FutureResult};
use futures::stream::Stream;
use futures::{Future, Poll};
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: MessageBody + '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,
})
}
}
pub struct LoggingMiddleware<S> {
service: S,
}
impl<S, B> Service for LoggingMiddleware<S>
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>
+ 'static,
S::Future: 'static,
B: MessageBody + '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, req: ServiceRequest) -> Self::Future {
Box::new(self.service.call(req).and_then(|res| {
Ok(res.map_body(|_, body| {
ResponseBody::Other(Body::Bytes(
body.fold(BytesMut::new(), move |mut body, chunk| {
body.extend_from_slice(&chunk);
Ok::<_, PayloadError>(body)
})
.and_then(move |bytes| {
println!("response body: {:?}", &bytes);
ok(bytes.freeze())
})
.wait()
.unwrap(),
))
}))
}))
}
}