tower_http/limit/
service.rs1use super::{RequestBodyLimitLayer, ResponseBody, ResponseFuture};
2use crate::body::Limited;
3use http::{Request, Response};
4use http_body::Body;
5use std::task::{Context, Poll};
6use tower_service::Service;
7
8#[derive(Clone, Copy, Debug)]
13pub struct RequestBodyLimit<S> {
14 pub(crate) inner: S,
15 pub(crate) limit: usize,
16}
17
18impl<S> RequestBodyLimit<S> {
19 pub fn new(inner: S, limit: usize) -> Self {
21 Self { inner, limit }
22 }
23
24 define_inner_service_accessors!();
25
26 pub fn layer(limit: usize) -> RequestBodyLimitLayer {
30 RequestBodyLimitLayer::new(limit)
31 }
32}
33
34impl<ReqBody, ResBody, S> Service<Request<ReqBody>> for RequestBodyLimit<S>
35where
36 ResBody: Body,
37 S: Service<Request<Limited<ReqBody>>, Response = Response<ResBody>>,
38{
39 type Response = Response<ResponseBody<ResBody>>;
40 type Error = S::Error;
41 type Future = ResponseFuture<S::Future>;
42
43 #[inline]
44 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
45 self.inner.poll_ready(cx)
46 }
47
48 fn call(&mut self, req: Request<ReqBody>) -> Self::Future {
49 let content_length = req
50 .headers()
51 .get(http::header::CONTENT_LENGTH)
52 .and_then(|value| value.to_str().ok()?.parse::<usize>().ok());
53
54 let body_limit = match content_length {
55 Some(len) if len > self.limit => return ResponseFuture::payload_too_large(),
56 Some(len) => self.limit.min(len),
57 None => self.limit,
58 };
59
60 let req = req.map(|body| Limited::new(http_body_util::Limited::new(body, body_limit)));
61
62 ResponseFuture::new(self.inner.call(req))
63 }
64}