Skip to content

Commit b35c144

Browse files
committed
adam review: changelog, enum config, shorter comment
1 parent 9be5395 commit b35c144

File tree

8 files changed

+52
-38
lines changed

8 files changed

+52
-38
lines changed

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
https://github.com/oxidecomputer/dropshot/compare/v0.16.4\...HEAD[Full list of commits]
1717

1818
* https://github.com/oxidecomputer/dropshot/pull/1475[#1475] Added `ClientSpecifiesVersionInHeader::on_missing` to provide a default version when the header is missing, intended for use when you're not in control of all clients
19+
* https://github.com/oxidecomputer/dropshot/pull/1448[#1448] Added support for gzipping responses when clients request it through the `Accept-Encoding` header. Compression is off by default: existing consumers won't see a behavior change unless they opt in with `compression: CompressionConfig::Gzip`.
1920

2021
== 0.16.4 (released 2025-09-04)
2122

dropshot/src/config.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ use serde::Serialize;
66
use std::net::SocketAddr;
77
use std::path::PathBuf;
88

9+
/// Configuration for response compression
10+
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize)]
11+
#[serde(rename_all = "lowercase")]
12+
pub enum CompressionConfig {
13+
/// Compression is disabled
14+
#[default]
15+
None,
16+
/// Gzip compression is enabled
17+
Gzip,
18+
}
19+
920
/// Raw [`rustls::ServerConfig`] TLS configuration for use with
1021
/// [`ConfigTls::Dynamic`]
1122
pub type RawTlsConfig = rustls::ServerConfig;
@@ -63,10 +74,9 @@ pub struct ConfigDropshot {
6374
/// is made to deal with headers that appear multiple times in a single
6475
/// request.
6576
pub log_headers: Vec<String>,
66-
/// Whether to enable gzip compression for responses when response contents
67-
/// allow it and clients ask for it through the Accept-Encoding header.
68-
/// Defaults to true.
69-
pub compression: bool,
77+
/// Whether to enable compression for responses (when response contents
78+
/// allow it and clients ask for it through the Accept-Encoding header).
79+
pub compression: CompressionConfig,
7080
}
7181

7282
/// Enum specifying options for how a Dropshot server should run its handler
@@ -123,7 +133,7 @@ impl Default for ConfigDropshot {
123133
default_request_body_max_bytes: 1024,
124134
default_handler_task_mode: HandlerTaskMode::Detached,
125135
log_headers: Default::default(),
126-
compression: false,
136+
compression: CompressionConfig::default(),
127137
}
128138
}
129139
}
@@ -142,7 +152,7 @@ struct DeserializedConfigDropshot {
142152
request_body_max_bytes: Option<InvalidConfig>,
143153
default_handler_task_mode: HandlerTaskMode,
144154
log_headers: Vec<String>,
145-
compression: bool,
155+
compression: CompressionConfig,
146156
}
147157

148158
impl From<DeserializedConfigDropshot> for ConfigDropshot {

dropshot/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,7 @@ pub use api_description::TagDetails;
907907
pub use api_description::TagExternalDocs;
908908
pub use body::Body;
909909
pub use compression::NoCompression;
910+
pub use config::CompressionConfig;
910911
pub use config::ConfigDropshot;
911912
pub use config::ConfigTls;
912913
pub use config::HandlerTaskMode;

dropshot/src/server.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::compression::add_vary_header;
77
use super::compression::apply_gzip_compression;
88
use super::compression::is_compressible_content_type;
99
use super::compression::should_compress_response;
10-
use super::config::{ConfigDropshot, ConfigTls};
10+
use super::config::{CompressionConfig, ConfigDropshot, ConfigTls};
1111
#[cfg(feature = "usdt-probes")]
1212
use super::dtrace::probes;
1313
use super::handler::HandlerError;
@@ -109,9 +109,8 @@ pub struct ServerConfig {
109109
/// is made to deal with headers that appear multiple times in a single
110110
/// request.
111111
pub log_headers: Vec<String>,
112-
/// Whether to enable gzip compression for responses when response contents
113-
/// allow it and clients ask for it through the Accept-Encoding header.
114-
pub compression: bool,
112+
/// Configuration for response compression.
113+
pub compression: CompressionConfig,
115114
}
116115

117116
/// See [`ServerBuilder`] instead.
@@ -991,19 +990,16 @@ async fn http_request_handle<C: ServerContext>(
991990
}
992991
};
993992

994-
if server.config.compression
993+
if matches!(server.config.compression, CompressionConfig::Gzip)
995994
&& is_compressible_content_type(response.headers())
996995
{
997996
// Add Vary: Accept-Encoding header for all compressible content
998997
// types. This needs to be there even if the response ends up not being
999-
// compressed because it tells caches how to handle the possibility that
1000-
// responses could be compressed or not.
1001-
//
1002-
// This tells caches (like browsers and CDNs) that the response content
1003-
// depends on the value of the Accept-Encoding header. Without this, a
1004-
// cache might mistakenly serve a compressed response to a client that
1005-
// cannot decompress it, or serve an uncompressed response to a client
1006-
// that could have benefited from compression.
998+
// compressed because it tells caches (like browsers and CDNs) that the
999+
// response content depends on the value of the Accept-Encoding header.
1000+
// Without this, a cache might mistakenly serve a compressed response to
1001+
// a client that cannot decompress it, or serve an uncompressed response
1002+
// to a client that could have benefited from compression.
10071003
add_vary_header(response.headers_mut());
10081004

10091005
if should_compress_response(

dropshot/src/websocket.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl tokio::io::AsyncWrite for WebsocketConnectionRaw {
349349
#[cfg(test)]
350350
mod tests {
351351
use crate::body::Body;
352-
use crate::config::HandlerTaskMode;
352+
use crate::config::{CompressionConfig, HandlerTaskMode};
353353
use crate::router::HttpRouter;
354354
use crate::server::{DropshotState, ServerConfig};
355355
use crate::{
@@ -385,7 +385,7 @@ mod tests {
385385
default_handler_task_mode:
386386
HandlerTaskMode::CancelOnDisconnect,
387387
log_headers: Default::default(),
388-
compression: true,
388+
compression: CompressionConfig::Gzip,
389389
},
390390
router: HttpRouter::new(),
391391
log: log.clone(),

dropshot/tests/integration-tests/config.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
use dropshot::test_util::read_config;
66
use dropshot::Body;
77
use dropshot::{
8-
ConfigDropshot, ConfigTls, HandlerTaskMode, HttpError, HttpResponseOk,
9-
RequestContext,
8+
CompressionConfig, ConfigDropshot, ConfigTls, HandlerTaskMode, HttpError,
9+
HttpResponseOk, RequestContext,
1010
};
1111
use dropshot::{HttpServer, ServerBuilder};
1212
use slog::o;
@@ -66,7 +66,7 @@ fn test_valid_config_all_settings() {
6666
default_request_body_max_bytes: 1048576,
6767
default_handler_task_mode: HandlerTaskMode::CancelOnDisconnect,
6868
log_headers: vec!["X-Forwarded-For".to_string()],
69-
compression: false,
69+
compression: CompressionConfig::default(),
7070
},
7171
);
7272
}
@@ -182,7 +182,7 @@ fn make_config(
182182
default_request_body_max_bytes: 1024,
183183
default_handler_task_mode,
184184
log_headers: Default::default(),
185-
compression: true,
185+
compression: CompressionConfig::Gzip,
186186
}
187187
}
188188

dropshot/tests/integration-tests/gzip.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ fn test_setup(
2525
test_name: &str,
2626
api: ApiDescription<usize>,
2727
) -> dropshot::test_util::TestContext<usize> {
28-
let config =
29-
dropshot::ConfigDropshot { compression: true, ..Default::default() };
28+
let config = dropshot::ConfigDropshot {
29+
compression: dropshot::CompressionConfig::Gzip,
30+
..Default::default()
31+
};
3032
let logctx = create_log_context(test_name);
3133
let log = logctx.log.new(slog::o!());
3234
dropshot::test_util::TestContext::new(
@@ -667,9 +669,11 @@ async fn test_no_compression_for_304_not_modified() {
667669

668670
#[tokio::test]
669671
async fn test_compression_config_disabled() {
670-
// Test that compression is disabled when config.compression = false (default)
671-
let config =
672-
dropshot::ConfigDropshot { compression: false, ..Default::default() };
672+
// Test that compression is disabled when compression = "none" (default)
673+
let config = dropshot::ConfigDropshot {
674+
compression: dropshot::CompressionConfig::None,
675+
..Default::default()
676+
};
673677
let logctx = create_log_context("compression_config_disabled");
674678
let log = logctx.log.new(slog::o!());
675679
let testctx = dropshot::test_util::TestContext::new(
@@ -695,9 +699,11 @@ async fn test_compression_config_disabled() {
695699

696700
#[tokio::test]
697701
async fn test_compression_config_enabled() {
698-
// Test that compression works when config.compression = true
699-
let config =
700-
dropshot::ConfigDropshot { compression: true, ..Default::default() };
702+
// Test that compression works when compression = "gzip"
703+
let config = dropshot::ConfigDropshot {
704+
compression: dropshot::CompressionConfig::Gzip,
705+
..Default::default()
706+
};
701707
let logctx = create_log_context("compression_config_enabled");
702708
let log = logctx.log.new(slog::o!());
703709
let testctx = dropshot::test_util::TestContext::new(
@@ -713,7 +719,7 @@ async fn test_compression_config_enabled() {
713719
let uri = client.url("/large-response");
714720
let mut response = get_gzip_response(client, &uri).await;
715721

716-
// Should be compressed since config.compression = true
722+
// Should be compressed since compression = "gzip"
717723
assert_gzip_encoded(&response);
718724

719725
// Verify the response can be decompressed

dropshot/tests/integration-tests/tls.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
//! mode, including certificate loading and supported modes.
55
66
use dropshot::{
7-
ConfigDropshot, ConfigTls, HandlerTaskMode, HttpResponseOk, HttpServer,
8-
ServerBuilder,
7+
CompressionConfig, ConfigDropshot, ConfigTls, HandlerTaskMode,
8+
HttpResponseOk, HttpServer, ServerBuilder,
99
};
1010
use slog::{o, Logger};
1111
use std::convert::TryFrom;
@@ -116,7 +116,7 @@ fn make_server(
116116
default_request_body_max_bytes: 1024,
117117
default_handler_task_mode: HandlerTaskMode::CancelOnDisconnect,
118118
log_headers: Default::default(),
119-
compression: true,
119+
compression: CompressionConfig::Gzip,
120120
};
121121
let config_tls = Some(ConfigTls::AsFile {
122122
cert_file: cert_file.to_path_buf(),
@@ -431,7 +431,7 @@ async fn test_server_is_https() {
431431
default_request_body_max_bytes: 1024,
432432
default_handler_task_mode: HandlerTaskMode::CancelOnDisconnect,
433433
log_headers: Default::default(),
434-
compression: true,
434+
compression: CompressionConfig::Gzip,
435435
};
436436
let config_tls = Some(ConfigTls::AsFile {
437437
cert_file: cert_file.path().to_path_buf(),

0 commit comments

Comments
 (0)