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:
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user