How to read a request body in an actix-web 4.0 middleware? #3545
-
use std::time::Instant;
use actix_service::forward_ready;
use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform};
use actix_web::{Error};
use actix_web::http::header::HeaderMap;
use futures::future::{ok, LocalBoxFuture, Ready};
use log::info;
use chrono::Local;
use serde_json::json;
pub struct Logging;
impl<S, B> Transform<S, ServiceRequest> for Logging
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> ,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Transform = LoggingMiddleware<S>;
type InitError = ();
type Future = Ready<Result<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<ServiceRequest> for LoggingMiddleware<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> ,
S::Future: 'static,
B: 'static,
{
type Response = ServiceResponse<B>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
forward_ready!(service);
fn call(&self, req: ServiceRequest) -> Self::Future {
let method = req.method().clone();
let path = req.path().to_string();
let query_string = req.query_string().to_string();
let headers = req.headers().clone();
let headers_json = headers_to_json(&headers);
let client_ip = req.peer_addr().map(|addr| addr.ip().to_string()).unwrap_or_default();
let start_instant = Instant::now();
let start_time_str = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
info!("================================ 网关请求响应日志 ===============================");
info!("请求路径: {}", path);
info!("请求方法: {}", method);
info!("查询参数: {}", query_string);
info!("请求头部: {}", headers_json);
info!("请求时间: {}", start_time_str);
info!("请求 IP: {}", client_ip);
// info!("请求数据: {:?}", req.body());
// how to get request body
let fut = self.service.call(req);
Box::pin(async move {
let res = fut.await?;
let duration = start_instant.elapsed();
let end_time_str = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
// how to get response body
// info!("响应数据: {:?}", res.response().body());
info!("响应时间: {}", end_time_str);
info!("执行耗时: {} 毫秒", duration.as_millis());
info!("==================================================================================");
Ok(res)
})
}
}
fn headers_to_json(headers: &HeaderMap) -> serde_json::Value {
let mut map = serde_json::Map::new();
for (key, value) in headers.iter() {
let values: Vec<String> = value.to_str().unwrap_or("").split(',').map(|s| s.trim().to_string()).collect();
map.insert(key.to_string(), json!(values));
}
json!(map)
} |
Beta Was this translation helpful? Give feedback.
Answered by
robjtede
Jan 6, 2025
Replies: 1 comment
Answer selected by
robjtede
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
see examples: https://github.com/actix/examples/blob/1d55c08a7e0290610789aedf7b6bf1b17060ec66/middleware/various/src/read_request_body.rs#L54-L60