From 6189caa52119d531d6c3bf3c18ebe3660af25ba4 Mon Sep 17 00:00:00 2001 From: peter-formlogic Date: Wed, 14 Apr 2021 17:12:03 +0930 Subject: [PATCH] Adjust JSON limit to 2MB and report on sizes --- src/error.rs | 14 +++++++++----- src/types/json.rs | 32 +++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/error.rs b/src/error.rs index cc1a055b8..af149e147 100644 --- a/src/error.rs +++ b/src/error.rs @@ -86,9 +86,13 @@ impl ResponseError for UrlencodedError { #[derive(Debug, Display, Error)] #[non_exhaustive] pub enum JsonPayloadError { - /// Payload size is bigger than allowed. (default: 32kB) - #[display(fmt = "Json payload size is bigger than allowed")] - Overflow, + /// Payload size is bigger than allowed. (default: 2MB) + #[display( + fmt = "JSON payload ({} bytes) is larger than allowed (limit: {} bytes).", + size, + limit + )] + Overflow { size: usize, limit: usize }, /// Content type error #[display(fmt = "Content type error")] @@ -116,7 +120,7 @@ impl From for JsonPayloadError { impl ResponseError for JsonPayloadError { fn status_code(&self) -> StatusCode { match self { - Self::Overflow => StatusCode::PAYLOAD_TOO_LARGE, + Self::Overflow { size: _, limit: _ } => StatusCode::PAYLOAD_TOO_LARGE, Self::Serialize(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Payload(err) => err.status_code(), _ => StatusCode::BAD_REQUEST, @@ -203,7 +207,7 @@ mod tests { #[test] fn test_json_payload_error() { - let resp = JsonPayloadError::Overflow.error_response(); + let resp = JsonPayloadError::Overflow{size: 0, limit: 0}.error_response(); assert_eq!(resp.status(), StatusCode::PAYLOAD_TOO_LARGE); let resp = JsonPayloadError::ContentType.error_response(); assert_eq!(resp.status(), StatusCode::BAD_REQUEST); diff --git a/src/types/json.rs b/src/types/json.rs index 322e5cbf3..75ed68928 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -240,7 +240,7 @@ pub struct JsonConfig { } impl JsonConfig { - /// Set maximum accepted payload size. By default this limit is 32kB. + /// Set maximum accepted payload size. By default this limit is 2MB. pub fn limit(mut self, limit: usize) -> Self { self.limit = limit; self @@ -273,9 +273,11 @@ impl JsonConfig { } } +const DEFAULT_LIMIT: usize = 2_097_152; // 2 mb + /// Allow shared refs used as default. const DEFAULT_CONFIG: JsonConfig = JsonConfig { - limit: 32_768, // 2^15 bytes, (~32kB) + limit: DEFAULT_LIMIT, err_handler: None, content_type: None, }; @@ -349,7 +351,7 @@ where let payload = payload.take(); JsonBody::Body { - limit: 32_768, + limit: DEFAULT_LIMIT, length, payload, buf: BytesMut::with_capacity(8192), @@ -357,7 +359,7 @@ where } } - /// Set maximum accepted payload size. The default limit is 32kB. + /// Set maximum accepted payload size. The default limit is 2MB. pub fn limit(self, limit: usize) -> Self { match self { JsonBody::Body { @@ -368,7 +370,10 @@ where } => { if let Some(len) = length { if len > limit { - return JsonBody::Error(Some(JsonPayloadError::Overflow)); + return JsonBody::Error(Some(JsonPayloadError::Overflow { + size: len, + limit, + })); } } @@ -399,14 +404,19 @@ where limit, buf, payload, + length, .. } => loop { let res = ready!(Pin::new(&mut *payload).poll_next(cx)); match res { Some(chunk) => { let chunk = chunk?; - if (buf.len() + chunk.len()) > *limit { - return Poll::Ready(Err(JsonPayloadError::Overflow)); + let buf_len = buf.len() + chunk.len(); + if buf_len > *limit { + return Poll::Ready(Err(JsonPayloadError::Overflow { + size: length.unwrap_or(buf_len), + limit: *limit, + })); } else { buf.extend_from_slice(&chunk); } @@ -445,7 +455,7 @@ mod tests { fn json_eq(err: JsonPayloadError, other: JsonPayloadError) -> bool { match err { - JsonPayloadError::Overflow => matches!(other, JsonPayloadError::Overflow), + JsonPayloadError::Overflow { .. } => matches!(other, JsonPayloadError::Overflow { .. }), JsonPayloadError::ContentType => matches!(other, JsonPayloadError::ContentType), _ => false, } @@ -538,7 +548,7 @@ mod tests { let s = Json::::from_request(&req, &mut pl).await; assert!(format!("{}", s.err().unwrap()) - .contains("Json payload size is bigger than allowed")); + .contains("JSON payload (16 bytes) is larger than allowed (limit: 10 bytes).")); let (req, mut pl) = TestRequest::default() .insert_header(( @@ -589,7 +599,7 @@ mod tests { let json = JsonBody::::new(&req, &mut pl, None) .limit(100) .await; - assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow)); + assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow { size: 10000, limit: 100 })); let (req, mut pl) = TestRequest::default() .insert_header(( @@ -686,6 +696,6 @@ mod tests { assert!(s.is_err()); let err_str = s.err().unwrap().to_string(); - assert!(err_str.contains("Json payload size is bigger than allowed")); + assert!(err_str.contains("JSON payload (16 bytes) is larger than allowed (limit: 10 bytes).")); } }