rustapi_ws/
compression.rs1#[derive(Debug, Clone, Copy)]
7pub struct WsCompressionConfig {
8 pub min_size: usize,
10 pub window_bits: u8,
12 pub client_window_bits: u8,
14}
15
16impl Default for WsCompressionConfig {
17 fn default() -> Self {
18 Self {
19 min_size: 256,
20 window_bits: 15,
21 client_window_bits: 15,
22 }
23 }
24}
25
26impl WsCompressionConfig {
27 pub fn new() -> Self {
29 Self::default()
30 }
31
32 pub fn min_size(mut self, size: usize) -> Self {
34 self.min_size = size;
35 self
36 }
37
38 pub fn window_bits(mut self, bits: u8) -> Self {
40 self.window_bits = bits.clamp(9, 15);
41 self
42 }
43
44 pub fn client_window_bits(mut self, bits: u8) -> Self {
46 self.client_window_bits = bits.clamp(9, 15);
47 self
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use crate::WebSocketUpgrade;
55 use proptest::prelude::*;
56
57 proptest! {
58 #[test]
59 fn test_compression_negotiation(
60 min_size in 0usize..10000,
61 window_bits in 9u8..15,
62 client_window_bits in 9u8..15,
63 client_supports_compression in proptest::bool::ANY,
64 ) {
65 let config = WsCompressionConfig::new()
66 .min_size(min_size)
67 .window_bits(window_bits)
68 .client_window_bits(client_window_bits);
69
70 let client_extensions = if client_supports_compression {
71 Some("permessage-deflate; client_max_window_bits".to_string())
72 } else {
73 None
74 };
75
76 let upgrade = WebSocketUpgrade::new(
77 "dGhlIHNhbXBsZSBub25jZQ==".to_string(),
78 client_extensions,
79 None, )
81 .compress(config);
82
83 let response = upgrade.into_response_inner();
84 let ext_header = response.headers().get("Sec-WebSocket-Extensions");
85
86 if client_supports_compression {
87 assert!(ext_header.is_some(), "Header missing when client supports compression");
88 let header_str = ext_header.unwrap().to_str().unwrap();
89 assert!(header_str.contains("permessage-deflate"));
90
91 if window_bits < 15 {
92 assert!(header_str.contains(&format!("server_max_window_bits={}", window_bits)));
93 }
94 if client_window_bits < 15 {
95 assert!(header_str.contains(&format!("client_max_window_bits={}", client_window_bits)));
96 }
97 } else {
98 assert!(ext_header.is_none());
99 }
100 }
101 }
102}