diff --git a/middleware/Cargo.toml b/middleware/Cargo.toml index da904716..84e66433 100644 --- a/middleware/Cargo.toml +++ b/middleware/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "middleware-example" version = "0.1.0" -authors = ["Gorm Casper "] +authors = ["Gorm Casper ", "Sven-Hendrik Haase "] edition = "2018" workspace = ".." diff --git a/middleware/README.md b/middleware/README.md index 401b9fd9..68a13c8b 100644 --- a/middleware/README.md +++ b/middleware/README.md @@ -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. diff --git a/middleware/src/main.rs b/middleware/src/main.rs index 49dfb98f..d4ff9e3e 100644 --- a/middleware/src/main.rs +++ b/middleware/src/main.rs @@ -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()); diff --git a/middleware/src/read_body.rs b/middleware/src/read_request_body.rs similarity index 100% rename from middleware/src/read_body.rs rename to middleware/src/read_request_body.rs diff --git a/middleware/src/read_response_body.rs b/middleware/src/read_response_body.rs new file mode 100644 index 00000000..f20be35d --- /dev/null +++ b/middleware/src/read_response_body.rs @@ -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 Transform for Logging +where + S: Service, Error = Error>, + S::Future: 'static, + B: MessageBody + 'static, +{ + type Request = ServiceRequest; + type Response = ServiceResponse; + type Error = Error; + type InitError = (); + type Transform = LoggingMiddleware; + type Future = FutureResult; + + fn new_transform(&self, service: S) -> Self::Future { + ok(LoggingMiddleware { + service, + }) + } +} + +pub struct LoggingMiddleware { + service: S, +} + +impl Service for LoggingMiddleware +where + S: Service, Error = Error> + + 'static, + S::Future: 'static, + B: MessageBody + 'static, +{ + type Request = ServiceRequest; + type Response = ServiceResponse; + type Error = Error; + type Future = Box>; + + 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(), + )) + })) + })) + } +}