use bytes::Bytes;
use http_body_util::BodyExt;
use hyper::{Request, Response};
use tracing::info;
pub type BoxBody = http_body_util::combinators::BoxBody<Bytes, hyper::Error>;
pub trait RequestHandler: Send + Sync {
fn handle_request(&self, req: &mut Request<BoxBody>);
fn handle_response(&self, res: &mut Response<BoxBody>);
}
pub struct LoggingHandler;
impl RequestHandler for LoggingHandler {
fn handle_request(&self, req: &mut Request<BoxBody>) {
let path = req.uri().path();
let display_uri = if req.uri().query().is_some() {
format!("{path}?<redacted>")
} else {
path.to_string()
};
info!(">> {} {} {:?}", req.method(), display_uri, req.version());
}
fn handle_response(&self, res: &mut Response<BoxBody>) {
info!("<< {}", res.status());
}
}
pub fn boxed_body<B>(body: B) -> BoxBody
where
B: hyper::body::Body<Data = Bytes, Error = hyper::Error> + Send + Sync + 'static,
{
body.boxed()
}
pub fn full_boxed_body(bytes: Bytes) -> BoxBody {
http_body_util::Full::new(bytes)
.map_err(|never| match never {})
.boxed()
}
pub fn extract_body_bytes(req: &mut Request<BoxBody>) -> Bytes {
let body = std::mem::replace(req.body_mut(), empty_boxed_body());
futures_util::FutureExt::now_or_never(async {
body.collect().await.map(|c| c.to_bytes()).unwrap_or_default()
})
.unwrap_or_default()
}
pub fn extract_response_body_bytes(res: &mut Response<BoxBody>) -> Bytes {
let body = std::mem::replace(res.body_mut(), empty_boxed_body());
futures_util::FutureExt::now_or_never(async {
body.collect().await.map(|c| c.to_bytes()).unwrap_or_default()
})
.unwrap_or_default()
}
pub fn put_body_back(req: &mut Request<BoxBody>, bytes: Bytes) {
*req.body_mut() = full_boxed_body(bytes);
}
pub fn put_response_body_back(res: &mut Response<BoxBody>, bytes: Bytes) {
*res.body_mut() = full_boxed_body(bytes);
}
pub fn empty_boxed_body() -> BoxBody {
http_body_util::Empty::new()
.map_err(|never| match never {})
.boxed()
}
#[derive(Clone)]
pub struct Dropped;
#[derive(Clone)]
pub struct Buffered;