mockforge_http/middleware/
response_buffer.rs1use axum::{body::Body, extract::Request, http::Response, middleware::Next};
7use serde_json::Value;
8
9#[derive(Clone)]
11pub struct BufferedResponse {
12 pub status: u16,
14 pub headers: axum::http::HeaderMap,
16 pub body: axum::body::Bytes,
18}
19
20impl BufferedResponse {
21 pub fn json(&self) -> Option<Value> {
23 serde_json::from_slice(&self.body).ok()
24 }
25
26 pub fn text(&self) -> String {
28 String::from_utf8_lossy(&self.body).to_string()
29 }
30}
31
32pub async fn buffer_response_middleware(req: Request, next: Next) -> Response<Body> {
38 let response = next.run(req).await;
40
41 let (parts, body) = response.into_parts();
43
44 let body_bytes = match axum::body::to_bytes(body, usize::MAX).await {
46 Ok(bytes) => bytes,
47 Err(e) => {
48 tracing::warn!("Failed to buffer response body: {}", e);
49 return Response::builder()
51 .status(axum::http::StatusCode::INTERNAL_SERVER_ERROR)
52 .body(Body::from("Failed to buffer response"))
53 .unwrap();
54 }
55 };
56
57 let buffered = BufferedResponse {
59 status: parts.status.as_u16(),
60 headers: parts.headers.clone(),
61 body: body_bytes.clone(),
62 };
63
64 let mut response_builder = Response::builder().status(parts.status).version(parts.version);
71
72 for (name, value) in parts.headers.iter() {
74 response_builder = response_builder.header(name, value);
75 }
76
77 let mut response = response_builder.body(Body::from(body_bytes)).unwrap();
79
80 response.extensions_mut().insert(buffered);
82
83 response
84}
85
86pub fn get_buffered_response(response: &Response<Body>) -> Option<BufferedResponse> {
88 response.extensions().get::<BufferedResponse>().cloned()
89}