awc: add camel_case headers api (#3953)

* Add camel-case functions for websocket request

* Add camel-case support for connection upgrade

* Fix camel case in encode_headers

* tweak

---------

Co-authored-by: Yuki Okushi <huyuumi.dev@gmail.com>
This commit is contained in:
Ali Mirghasemi 2026-02-27 02:29:41 +03:30 committed by GitHub
parent 975b6efe89
commit e2eb53bcce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 4 deletions

View File

@ -2,6 +2,10 @@
## Unreleased ## Unreleased
- Encode the HTTP/1 `Connection: Upgrade` header in Camel-Case when camel-case header formatting is enabled.[#3953]
[#3953]: https://github.com/actix/actix-web/pull/3953
## 3.12.0 ## 3.12.0
- Minimum supported Rust version (MSRV) is now 1.88. - Minimum supported Rust version (MSRV) is now 1.88.

View File

@ -111,7 +111,13 @@ pub(crate) trait MessageType: Sized {
// Connection // Connection
match conn_type { match conn_type {
ConnectionType::Upgrade => dst.put_slice(b"connection: upgrade\r\n"), ConnectionType::Upgrade => {
if camel_case {
dst.put_slice(b"Connection: Upgrade\r\n")
} else {
dst.put_slice(b"connection: upgrade\r\n")
}
}
ConnectionType::KeepAlive if version < Version::HTTP_11 => { ConnectionType::KeepAlive if version < Version::HTTP_11 => {
if camel_case { if camel_case {
dst.put_slice(b"Connection: keep-alive\r\n") dst.put_slice(b"Connection: keep-alive\r\n")
@ -580,6 +586,16 @@ mod tests {
assert!(data.contains("Date: date\r\n")); assert!(data.contains("Date: date\r\n"));
assert!(data.contains("Upgrade-Insecure-Requests: 1\r\n")); assert!(data.contains("Upgrade-Insecure-Requests: 1\r\n"));
let _ = head.encode_headers(
&mut bytes,
Version::HTTP_11,
BodySize::None,
ConnectionType::Upgrade,
&ServiceConfig::default(),
);
let data = String::from_utf8(Vec::from(bytes.split().freeze().as_ref())).unwrap();
assert!(data.contains("Connection: Upgrade\r\n"));
let _ = head.encode_headers( let _ = head.encode_headers(
&mut bytes, &mut bytes,
Version::HTTP_11, Version::HTTP_11,

View File

@ -61,14 +61,15 @@ impl RequestHead {
&mut self.headers &mut self.headers
} }
/// Is to uppercase headers with Camel-Case. /// Returns whether headers should be sent in Camel-Case.
/// Default is `false` ///
/// Default is `false`.
#[inline] #[inline]
pub fn camel_case_headers(&self) -> bool { pub fn camel_case_headers(&self) -> bool {
self.flags.contains(Flags::CAMEL_CASE) self.flags.contains(Flags::CAMEL_CASE)
} }
/// Set `true` to send headers which are formatted as Camel-Case. /// Sets whether to send headers formatted as Camel-Case.
#[inline] #[inline]
pub fn set_camel_case_headers(&mut self, val: bool) { pub fn set_camel_case_headers(&mut self, val: bool) {
if val { if val {

View File

@ -2,6 +2,10 @@
## Unreleased ## Unreleased
- Add camel-case header controls to `WebsocketsRequest` via `camel_case_headers()` and `set_camel_case_headers()`. [#3953]
[#3953]: https://github.com/actix/actix-web/pull/3953
## 3.8.2 ## 3.8.2
- Minimum supported Rust version (MSRV) is now 1.88. - Minimum supported Rust version (MSRV) is now 1.88.

View File

@ -245,6 +245,21 @@ impl WebsocketsRequest {
self.header(AUTHORIZATION, format!("Bearer {}", token)) self.header(AUTHORIZATION, format!("Bearer {}", token))
} }
/// Returns whether headers should be sent in Camel-Case.
///
/// Default is `false`.
#[inline]
pub fn camel_case_headers(&self) -> bool {
self.head.camel_case_headers()
}
/// Sets whether to send headers formatted as Camel-Case.
#[inline]
pub fn set_camel_case_headers(mut self, val: bool) -> Self {
self.head.set_camel_case_headers(val);
self
}
/// Complete request construction and connect to a WebSocket server. /// Complete request construction and connect to a WebSocket server.
pub async fn connect( pub async fn connect(
mut self, mut self,
@ -529,6 +544,12 @@ mod tests {
let _ = req.connect(); let _ = req.connect();
} }
#[actix_rt::test]
async fn camel_case_headers() {
let req = Client::new().ws("/").set_camel_case_headers(true);
assert!(req.camel_case_headers());
}
#[actix_rt::test] #[actix_rt::test]
async fn basics() { async fn basics() {
let req = Client::new() let req = Client::new()