Skip to content

Commit 5029e94

Browse files
aaryanpuniaskeptrunedev
authored andcommitted
enhancement: make content-type header optional for json payloads
1 parent 32ef0e4 commit 5029e94

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

server/src/errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ pub fn custom_json_error_handler(
119119
) -> actix_web::Error {
120120
let (error_message, solution) = match &err {
121121
JsonPayloadError::ContentType => (
122-
"Content type error",
123-
"Ensure that the content type of the request body is set to application/json."
122+
"Content type header error",
123+
"Ensure the content type request header of the HTTP request is set as `Content-Type: application/json`."
124124
),
125125
JsonPayloadError::Payload(_) => (
126126
"Payload error",

server/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ pub fn main() -> std::io::Result<()> {
595595
App::new()
596596
.wrap(Cors::permissive())
597597
.app_data(PayloadConfig::new(134200000))
598+
.wrap(middleware::json_middleware::JsonMiddlewareFactory)
598599
.app_data(json_cfg.clone())
599600
.app_data(
600601
web::PathConfig::default()
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use actix_http::header::HeaderValue;
2+
use actix_web::{
3+
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
4+
Error,
5+
};
6+
use futures_util::future::LocalBoxFuture;
7+
use std::{
8+
future::{ready, Ready},
9+
rc::Rc,
10+
};
11+
12+
pub struct JsonMiddleware<S> {
13+
service: Rc<S>,
14+
}
15+
16+
impl<S, B> Service<ServiceRequest> for JsonMiddleware<S>
17+
where
18+
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
19+
S::Future: 'static,
20+
B: 'static,
21+
{
22+
type Response = ServiceResponse<B>;
23+
type Error = Error;
24+
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
25+
26+
forward_ready!(service);
27+
fn call(&self, mut req: ServiceRequest) -> Self::Future {
28+
// Clone the Rc pointers so we can move them into the async block.
29+
let srv = self.service.clone();
30+
Box::pin(async move {
31+
if req
32+
.headers()
33+
.get(actix_http::header::CONTENT_TYPE)
34+
.is_none()
35+
{
36+
req.headers_mut().insert(
37+
actix_http::header::CONTENT_TYPE,
38+
HeaderValue::from_static("application/json"),
39+
);
40+
}
41+
let res = srv.call(req).await?;
42+
Ok(res)
43+
})
44+
}
45+
}
46+
47+
pub struct JsonMiddlewareFactory;
48+
49+
impl<S, B> Transform<S, ServiceRequest> for JsonMiddlewareFactory
50+
where
51+
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
52+
S::Future: 'static,
53+
B: 'static,
54+
{
55+
type Response = ServiceResponse<B>;
56+
type Error = Error;
57+
type InitError = ();
58+
type Transform = JsonMiddleware<S>;
59+
type Future = Ready<Result<Self::Transform, Self::InitError>>;
60+
61+
fn new_transform(&self, service: S) -> Self::Future {
62+
ready(Ok(JsonMiddleware {
63+
service: Rc::new(service),
64+
}))
65+
}
66+
}

server/src/middleware/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod api_version;
22
pub mod auth_middleware;
3+
pub mod json_middleware;

0 commit comments

Comments
 (0)