[feature request] Use anonymous function as handler parameter
axxop opened this issue · 2 comments
axxop commented
Thanks for your crate
My use case is that when I use with_http_handler/with_incoming_message_handler/with_outgoing_message_handler
, I want to store the request & response. In the current case, it looks like the only way to store it is to create global mutables using something like lazy_static. Switching to anonymous functions we can easily create Arc<Mutex<>>
in any context to store the data. what do you think about this?
omjadas commented
Hi,
This is possible now using the existing handlers
use hudsucker::{
async_trait::async_trait,
hyper::{body::Bytes, Body, Request, Response},
tungstenite::Message,
HttpContext, HttpHandler, MessageContext, MessageHandler, RequestOrResponse,
};
use std::sync::{Arc, Mutex};
#[derive(Clone)]
struct MyHttpHandler {
pub requests: Arc<Mutex<Vec<Request<Bytes>>>>,
pub responses: Arc<Mutex<Vec<Response<Bytes>>>>,
}
#[async_trait]
impl HttpHandler for MyHttpHandler {
async fn handle_request(
&mut self,
_ctx: &HttpContext,
req: Request<Body>,
) -> RequestOrResponse {
let (stored_req, req) = {
let (parts, body) = req.into_parts();
let mut builder = Request::builder()
.method(&parts.method)
.uri(&parts.uri)
.version(parts.version);
if let Some(h) = builder.headers_mut() {
*h = parts.headers.clone();
}
let bytes = hyper::body::to_bytes(body).await.unwrap();
(
builder.body(bytes.clone()).unwrap(),
Request::from_parts(parts, Body::from(bytes)),
)
};
self.requests.lock().unwrap().push(stored_req);
RequestOrResponse::Request(req)
}
async fn handle_response(&mut self, _ctx: &HttpContext, res: Response<Body>) -> Response<Body> {
let (stored_res, res) = {
let (parts, body) = res.into_parts();
let mut builder = Response::builder()
.status(parts.status)
.version(parts.version);
if let Some(h) = builder.headers_mut() {
*h = parts.headers.clone();
}
let bytes = hyper::body::to_bytes(body).await.unwrap();
(
builder.body(bytes.clone()).unwrap(),
Response::from_parts(parts, Body::from(bytes)),
)
};
self.responses.lock().unwrap().push(stored_res);
res
}
}
#[derive(Clone)]
struct MyMessageHandler {
pub messages: Arc<Mutex<Vec<Message>>>,
}
#[async_trait]
impl MessageHandler for MyMessageHandler {
async fn handle_message(&mut self, _ctx: &MessageContext, msg: Message) -> Option<Message> {
self.messages.lock().unwrap().push(msg.clone());
Some(msg)
}
}
axxop commented
Thanks for your reply, this answered my question.