From 539e86a54420b6e3f6dd2273d0abfcecc2825cbf Mon Sep 17 00:00:00 2001 From: Vinicius Buzzacaro Date: Mon, 10 Nov 2025 21:40:11 -0300 Subject: [PATCH 1/5] Change the return type of the method content_type from &str to Option<&str> --- actix-http/src/http_message.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/actix-http/src/http_message.rs b/actix-http/src/http_message.rs index 2800f40ba..8c38e3cff 100644 --- a/actix-http/src/http_message.rs +++ b/actix-http/src/http_message.rs @@ -46,13 +46,11 @@ pub trait HttpMessage: Sized { /// Read the request content type. If request did not contain a *Content-Type* header, an empty /// string is returned. - fn content_type(&self) -> &str { - if let Some(content_type) = self.headers().get(header::CONTENT_TYPE) { - if let Ok(content_type) = content_type.to_str() { - return content_type.split(';').next().unwrap().trim(); - } - } - "" + fn content_type(&self) -> Option<&str> { + self.headers() + .get(header::CONTENT_TYPE) + .and_then(|ct| ct.to_str().ok()) + .map(|ct| ct.split(';').next().unwrap().trim()) } /// Get content type encoding. @@ -142,13 +140,13 @@ mod tests { let req = TestRequest::default() .insert_header(("content-type", "text/plain")) .finish(); - assert_eq!(req.content_type(), "text/plain"); + assert_eq!(req.content_type(), Some("text/plain")); let req = TestRequest::default() .insert_header(("content-type", "application/json; charset=utf-8")) .finish(); - assert_eq!(req.content_type(), "application/json"); + assert_eq!(req.content_type(), Some("application/json")); let req = TestRequest::default().finish(); - assert_eq!(req.content_type(), ""); + assert_eq!(req.content_type(), None); } #[test] From a992de888e89d7ee623b060562f2b78f179bbcc7 Mon Sep 17 00:00:00 2001 From: Vinicius Buzzacaro Date: Mon, 10 Nov 2025 21:40:42 -0300 Subject: [PATCH 2/5] Updated the tests to match the new signature --- actix-web/src/test/test_utils.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/actix-web/src/test/test_utils.rs b/actix-web/src/test/test_utils.rs index 4540d8a6b..5c8c4e144 100644 --- a/actix-web/src/test/test_utils.rs +++ b/actix-web/src/test/test_utils.rs @@ -505,7 +505,10 @@ mod tests { .set_form(&payload) .to_request(); - assert_eq!(req.content_type(), "application/x-www-form-urlencoded"); + assert_eq!( + req.content_type().unwrap(), + "application/x-www-form-urlencoded" + ); let result: Person = call_and_read_body_json(&app, req).await; assert_eq!(&result.id, "12345"); @@ -549,7 +552,7 @@ mod tests { .set_json(&payload) .to_request(); - assert_eq!(req.content_type(), "application/json"); + assert_eq!(req.content_type(), Some("application/json")); let result: Person = call_and_read_body_json(&app, req).await; assert_eq!(&result.id, "12345"); From 1c8c860e7d1c95607359417f11e16e3a3719fdff Mon Sep 17 00:00:00 2001 From: Vinicius Buzzacaro Date: Mon, 10 Nov 2025 21:41:08 -0300 Subject: [PATCH 3/5] Minor tweaks to match new signature --- actix-web/src/types/form.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actix-web/src/types/form.rs b/actix-web/src/types/form.rs index d6381b990..91ae702c8 100644 --- a/actix-web/src/types/form.rs +++ b/actix-web/src/types/form.rs @@ -289,7 +289,7 @@ impl UrlEncoded { /// Create a new future to decode a URL encoded request payload. pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self { // check content type - if req.content_type().to_lowercase() != "application/x-www-form-urlencoded" { + if req.content_type() != Some("application/x-www-form-urlencoded") { return Self::err(UrlencodedError::ContentType); } let encoding = match req.encoding() { From 5037f9acd7b1652b7a64be38a4221a1bf129e115 Mon Sep 17 00:00:00 2001 From: Vinicius Buzzacaro Date: Mon, 10 Nov 2025 21:52:40 -0300 Subject: [PATCH 4/5] Updated documentation --- actix-http/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 33f9d2017..c1db85509 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -2,6 +2,10 @@ ## Unreleased +## 3.11.3 + +- Update `HttpMessage`s `content_type` method to return `Option<&str>` instead of `&str`. + ## 3.11.2 - Properly wake Payload receivers when feeding errors or EOF. From 9ea97a676ae9097e07114ab18d16a6a330faad7e Mon Sep 17 00:00:00 2001 From: Vinicius Buzzacaro Date: Mon, 10 Nov 2025 22:25:04 -0300 Subject: [PATCH 5/5] Content type is now being compared ignoring case --- actix-web/src/types/form.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/actix-web/src/types/form.rs b/actix-web/src/types/form.rs index 91ae702c8..109d220e8 100644 --- a/actix-web/src/types/form.rs +++ b/actix-web/src/types/form.rs @@ -289,14 +289,17 @@ impl UrlEncoded { /// Create a new future to decode a URL encoded request payload. pub fn new(req: &HttpRequest, payload: &mut Payload) -> Self { // check content type - if req.content_type() != Some("application/x-www-form-urlencoded") { + let encoding_error = req + .content_type() + .map(|ct| !ct.eq_ignore_ascii_case("application/x-www-form-urlencoded")) + .unwrap_or(true); + if encoding_error { return Self::err(UrlencodedError::ContentType); } let encoding = match req.encoding() { Ok(enc) => enc, Err(_) => return Self::err(UrlencodedError::ContentType), }; - let mut len = None; if let Some(l) = req.headers().get(&CONTENT_LENGTH) { if let Ok(s) = l.to_str() {