gatel_core/hoops/
buffer.rs1use salvo::http::StatusCode;
2use salvo::{Depot, FlowCtrl, Request, Response, async_trait};
3use tracing::debug;
4
5pub struct BufferLimitHoop {
13 max_request_body: Option<usize>,
14 max_response_body: Option<usize>,
15}
16
17impl BufferLimitHoop {
18 pub fn new(max_request_body: Option<usize>, max_response_body: Option<usize>) -> Self {
19 Self {
20 max_request_body,
21 max_response_body,
22 }
23 }
24}
25
26#[async_trait]
27impl salvo::Handler for BufferLimitHoop {
28 async fn handle(
29 &self,
30 req: &mut Request,
31 depot: &mut Depot,
32 res: &mut Response,
33 ctrl: &mut FlowCtrl,
34 ) {
35 if let Some(max_req) = self.max_request_body
37 && let Some(content_length) = req
38 .headers()
39 .get(http::header::CONTENT_LENGTH)
40 .and_then(|v| v.to_str().ok())
41 .and_then(|s| s.parse::<usize>().ok())
42 && content_length > max_req
43 {
44 debug!(
45 content_length,
46 limit = max_req,
47 "request body exceeds limit, returning 413"
48 );
49 res.status_code(StatusCode::PAYLOAD_TOO_LARGE);
50 res.body("Payload Too Large");
51 ctrl.skip_rest();
52 return;
53 }
54
55 ctrl.call_next(req, depot, res).await;
57
58 if let Some(max_resp) = self.max_response_body
59 && let Some(content_length) = res
60 .headers()
61 .get(http::header::CONTENT_LENGTH)
62 .and_then(|v| v.to_str().ok())
63 .and_then(|s| s.parse::<usize>().ok())
64 && content_length > max_resp
65 {
66 debug!(
67 content_length,
68 limit = max_resp,
69 "response body exceeds limit, returning 502"
70 );
71 res.status_code(StatusCode::BAD_GATEWAY);
72 res.body("Bad Gateway: response body too large");
73 }
74 }
75}