1
0
mirror of https://github.com/fafhrd91/actix-web synced 2025-07-02 17:24:39 +02:00

implement DEFLATE compression

This commit is contained in:
Park Joon-Kyu
2024-11-06 21:57:48 +09:00
parent ecb4616d2a
commit c97b6ac0d4
7 changed files with 1029 additions and 122 deletions

View File

@ -63,9 +63,15 @@ rustls-0_20 = ["tls-rustls-0_20", "actix-tls/rustls-0_20"]
# TLS via Rustls v0.21
rustls-0_21 = ["tls-rustls-0_21", "actix-tls/rustls-0_21"]
# TLS via Rustls v0.22 (WebPKI roots)
rustls-0_22-webpki-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-webpki-roots"]
rustls-0_22-webpki-roots = [
"tls-rustls-0_22",
"actix-tls/rustls-0_22-webpki-roots",
]
# TLS via Rustls v0.22 (Native roots)
rustls-0_22-native-roots = ["tls-rustls-0_22", "actix-tls/rustls-0_22-native-roots"]
rustls-0_22-native-roots = [
"tls-rustls-0_22",
"actix-tls/rustls-0_22-native-roots",
]
# TLS via Rustls v0.23
rustls-0_23 = ["tls-rustls-0_23", "actix-tls/rustls-0_23"]
# TLS via Rustls v0.23 (WebPKI roots)
@ -79,6 +85,8 @@ compress-brotli = ["actix-http/compress-brotli", "__compress"]
compress-gzip = ["actix-http/compress-gzip", "__compress"]
# Zstd algorithm content-encoding support
compress-zstd = ["actix-http/compress-zstd", "__compress"]
# Deflate compression for WebSocket
compress-ws-deflate = ["actix-http/compress-ws-deflate"]
# Cookie parsing and cookie jar
cookies = ["dep:cookie"]
@ -112,7 +120,7 @@ futures-util = { version = "0.3.17", default-features = false, features = ["allo
h2 = "0.3.26"
http = "0.2.7"
itoa = "1"
log =" 0.4"
log = " 0.4"
mime = "0.3"
percent-encoding = "2.1"
pin-project-lite = "0.2"
@ -125,8 +133,12 @@ tokio = { version = "1.24.2", features = ["sync"] }
cookie = { version = "0.16", features = ["percent-encode"], optional = true }
tls-openssl = { package = "openssl", version = "0.10.55", optional = true }
tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = ["dangerous_configuration"] }
tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = ["dangerous_configuration"] }
tls-rustls-0_20 = { package = "rustls", version = "0.20", optional = true, features = [
"dangerous_configuration",
] }
tls-rustls-0_21 = { package = "rustls", version = "0.21", optional = true, features = [
"dangerous_configuration",
] }
tls-rustls-0_22 = { package = "rustls", version = "0.22", optional = true }
tls-rustls-0_23 = { package = "rustls", version = "0.23", optional = true, default-features = false }
@ -151,7 +163,7 @@ rcgen = "0.13"
rustls-pemfile = "2"
tokio = { version = "1.24.2", features = ["rt-multi-thread", "macros"] }
zstd = "0.13"
tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests
tls-rustls-0_23 = { package = "rustls", version = "0.23" } # add rustls 0.23 with default features to make aws_lc_rs work in tests
[lints]
workspace = true

View File

@ -30,6 +30,8 @@ use std::{fmt, net::SocketAddr, str};
use actix_codec::Framed;
pub use actix_http::ws::{CloseCode, CloseReason, Codec, Frame, Message};
#[cfg(feature = "compress-ws-deflate")]
pub use actix_http::ws::{DeflateCompressionLevel, DeflateSessionParameters};
use actix_http::{ws, Payload, RequestHead};
use actix_rt::time::timeout;
use actix_service::Service as _;
@ -59,6 +61,9 @@ pub struct WebsocketsRequest {
server_mode: bool,
config: ClientConfig,
#[cfg(feature = "compress-ws-deflate")]
deflate_compression_level: Option<DeflateCompressionLevel>,
#[cfg(feature = "cookies")]
cookies: Option<CookieJar>,
}
@ -94,6 +99,8 @@ impl WebsocketsRequest {
protocols: None,
max_size: 65_536,
server_mode: false,
#[cfg(feature = "compress-ws-deflate")]
deflate_compression_level: None,
#[cfg(feature = "cookies")]
cookies: None,
}
@ -249,6 +256,22 @@ impl WebsocketsRequest {
self.header(AUTHORIZATION, format!("Bearer {}", token))
}
/// Enable DEFLATE compression
#[cfg(feature = "compress-ws-deflate")]
pub fn deflate(
mut self,
compression_level: Option<DeflateCompressionLevel>,
params: DeflateSessionParameters,
) -> Self {
use actix_http::header::TryIntoHeaderPair;
// Assume session parameters are always valid.
let (key, value) = params.try_into_pair().unwrap();
self.deflate_compression_level = compression_level;
self.header(key, value)
}
/// Complete request construction and connect to a WebSocket server.
pub async fn connect(
mut self,
@ -409,17 +432,51 @@ impl WebsocketsRequest {
return Err(WsClientError::MissingWebSocketAcceptHeader);
};
// response and ws framed
Ok((
ClientResponse::new(head, Payload::None),
framed.into_map_codec(|_| {
if server_mode {
ws::Codec::new().max_size(max_size)
#[cfg(feature = "compress-ws-deflate")]
let framed = {
let selected_parameter = head
.headers
.get_all(header::SEC_WEBSOCKET_EXTENSIONS)
.filter_map(|header| {
if let Ok(header_str) = header.to_str() {
Some(DeflateSessionParameters::from_extension_header(header_str))
} else {
None
}
})
.flatten()
.filter_map(Result::ok)
.next();
framed.into_map_codec(move |_| {
let codec = if let Some(parameter) = selected_parameter.clone() {
let context = parameter.create_context(self.deflate_compression_level, false);
Codec::new_deflate(context)
} else {
ws::Codec::new().max_size(max_size).client_mode()
Codec::new()
}
}),
))
.max_size(max_size);
if server_mode {
codec
} else {
codec.client_mode()
}
})
};
#[cfg(not(feature = "compress-ws-deflate"))]
let framed = framed.into_map_codec(move |_| {
let codec = Codec::new().max_size(max_size);
if server_mode {
codec
} else {
codec.client_mode()
}
});
// response and ws framed
Ok((ClientResponse::new(head, Payload::None), framed))
}
}