2022-02-22 12:12:17 +00:00
|
|
|
use std::{
|
|
|
|
future::{ready, Future, Ready},
|
|
|
|
marker::PhantomData,
|
|
|
|
pin::Pin,
|
|
|
|
task::{Context, Poll},
|
|
|
|
};
|
2019-12-07 23:59:24 +06:00
|
|
|
|
2022-02-22 12:12:17 +00:00
|
|
|
use actix_web::{
|
|
|
|
body::{BodySize, MessageBody},
|
|
|
|
dev::{self, Service, ServiceRequest, ServiceResponse, Transform},
|
|
|
|
web::{Bytes, BytesMut},
|
|
|
|
Error,
|
|
|
|
};
|
2019-09-11 15:12:08 +02:00
|
|
|
|
|
|
|
pub struct Logging;
|
|
|
|
|
2022-01-29 16:39:58 +00:00
|
|
|
impl<S: 'static, B> Transform<S, ServiceRequest> for Logging
|
2019-09-11 15:12:08 +02:00
|
|
|
where
|
2022-01-29 16:39:58 +00:00
|
|
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
2019-09-18 04:37:35 +02:00
|
|
|
B: MessageBody + 'static,
|
2019-09-11 15:12:08 +02:00
|
|
|
{
|
2019-09-18 06:16:47 +02:00
|
|
|
type Response = ServiceResponse<BodyLogger<B>>;
|
2019-09-11 15:12:08 +02:00
|
|
|
type Error = Error;
|
|
|
|
type InitError = ();
|
|
|
|
type Transform = LoggingMiddleware<S>;
|
2019-12-07 23:59:24 +06:00
|
|
|
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
2019-09-11 15:12:08 +02:00
|
|
|
|
|
|
|
fn new_transform(&self, service: S) -> Self::Future {
|
2022-01-29 16:39:58 +00:00
|
|
|
ready(Ok(LoggingMiddleware { service }))
|
2019-09-11 15:12:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct LoggingMiddleware<S> {
|
2019-09-18 04:37:35 +02:00
|
|
|
service: S,
|
2019-09-11 15:12:08 +02:00
|
|
|
}
|
|
|
|
|
2022-01-29 16:39:58 +00:00
|
|
|
impl<S, B> Service<ServiceRequest> for LoggingMiddleware<S>
|
2019-09-11 15:12:08 +02:00
|
|
|
where
|
2022-01-29 16:39:58 +00:00
|
|
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
2019-09-18 06:16:47 +02:00
|
|
|
B: MessageBody,
|
2019-09-11 15:12:08 +02:00
|
|
|
{
|
2019-09-18 06:16:47 +02:00
|
|
|
type Response = ServiceResponse<BodyLogger<B>>;
|
2019-09-11 15:12:08 +02:00
|
|
|
type Error = Error;
|
2019-09-18 06:16:47 +02:00
|
|
|
type Future = WrapperStream<S, B>;
|
2019-09-11 15:12:08 +02:00
|
|
|
|
2022-01-29 16:39:58 +00:00
|
|
|
dev::forward_ready!(service);
|
2019-09-11 15:12:08 +02:00
|
|
|
|
2022-01-29 16:39:58 +00:00
|
|
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
2019-09-18 06:16:47 +02:00
|
|
|
WrapperStream {
|
|
|
|
fut: self.service.call(req),
|
|
|
|
_t: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
#[pin_project::pin_project]
|
2019-09-18 06:16:47 +02:00
|
|
|
pub struct WrapperStream<S, B>
|
|
|
|
where
|
|
|
|
B: MessageBody,
|
2022-01-29 16:39:58 +00:00
|
|
|
S: Service<ServiceRequest>,
|
2019-09-18 06:16:47 +02:00
|
|
|
{
|
2019-12-07 23:59:24 +06:00
|
|
|
#[pin]
|
2019-09-18 06:16:47 +02:00
|
|
|
fut: S::Future,
|
|
|
|
_t: PhantomData<(B,)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<S, B> Future for WrapperStream<S, B>
|
|
|
|
where
|
|
|
|
B: MessageBody,
|
2022-01-29 16:39:58 +00:00
|
|
|
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
2019-09-18 06:16:47 +02:00
|
|
|
{
|
2019-12-07 23:59:24 +06:00
|
|
|
type Output = Result<ServiceResponse<BodyLogger<B>>, Error>;
|
2019-09-18 06:16:47 +02:00
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
2022-02-22 12:12:17 +00:00
|
|
|
let res = futures_util::ready!(self.project().fut.poll(cx));
|
2019-09-18 06:16:47 +02:00
|
|
|
|
2019-12-07 23:59:24 +06:00
|
|
|
Poll::Ready(res.map(|res| {
|
2022-01-29 16:39:58 +00:00
|
|
|
res.map_body(move |_, body| BodyLogger {
|
|
|
|
body,
|
|
|
|
body_accum: BytesMut::new(),
|
2019-09-18 06:16:47 +02:00
|
|
|
})
|
2019-12-07 23:59:24 +06:00
|
|
|
}))
|
2019-09-18 06:16:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-12 16:49:45 +01:00
|
|
|
#[pin_project::pin_project(PinnedDrop)]
|
2019-09-18 06:16:47 +02:00
|
|
|
pub struct BodyLogger<B> {
|
2020-09-12 16:49:45 +01:00
|
|
|
#[pin]
|
2022-01-29 16:39:58 +00:00
|
|
|
body: B,
|
2019-09-18 06:16:47 +02:00
|
|
|
body_accum: BytesMut,
|
|
|
|
}
|
|
|
|
|
2020-09-12 16:49:45 +01:00
|
|
|
#[pin_project::pinned_drop]
|
|
|
|
impl<B> PinnedDrop for BodyLogger<B> {
|
|
|
|
fn drop(self: Pin<&mut Self>) {
|
2019-09-18 06:16:47 +02:00
|
|
|
println!("response body: {:?}", self.body_accum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<B: MessageBody> MessageBody for BodyLogger<B> {
|
2022-01-29 16:39:58 +00:00
|
|
|
type Error = B::Error;
|
|
|
|
|
2019-09-18 06:16:47 +02:00
|
|
|
fn size(&self) -> BodySize {
|
|
|
|
self.body.size()
|
|
|
|
}
|
|
|
|
|
2020-09-12 16:49:45 +01:00
|
|
|
fn poll_next(
|
|
|
|
self: Pin<&mut Self>,
|
|
|
|
cx: &mut Context<'_>,
|
2022-01-29 16:39:58 +00:00
|
|
|
) -> Poll<Option<Result<Bytes, Self::Error>>> {
|
2020-09-12 16:49:45 +01:00
|
|
|
let this = self.project();
|
|
|
|
|
|
|
|
match this.body.poll_next(cx) {
|
2019-12-07 23:59:24 +06:00
|
|
|
Poll::Ready(Some(Ok(chunk))) => {
|
2020-09-12 16:49:45 +01:00
|
|
|
this.body_accum.extend_from_slice(&chunk);
|
2019-12-07 23:59:24 +06:00
|
|
|
Poll::Ready(Some(Ok(chunk)))
|
2019-09-18 06:16:47 +02:00
|
|
|
}
|
2019-12-07 23:59:24 +06:00
|
|
|
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
|
|
|
|
Poll::Ready(None) => Poll::Ready(None),
|
|
|
|
Poll::Pending => Poll::Pending,
|
2019-09-18 06:16:47 +02:00
|
|
|
}
|
2019-09-11 15:12:08 +02:00
|
|
|
}
|
|
|
|
}
|