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 Transform for Logging where S: Service, Error = Error>, S::Future: 'static, B: '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: Rc::new(RefCell::new(service)), }) } } pub struct LoggingMiddleware { // This is special: We need this to avoid lifetime issues. service: Rc>, } impl Service for LoggingMiddleware where S: Service, Error = Error> + 'static, S::Future: 'static, B: '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, 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)) }), ) } }