feat: enable all HTTP compression algorithms by default
- COMPRESSION_ALGORITHMS defaults to 'all' when unset - Support 'none'/'off' to explicitly disable compression - Add parse_compression_algorithms helper and unit tests - Update .env.example comment to reflect new default
This commit is contained in:
parent
634f733e36
commit
05b9a3a595
@ -28,7 +28,7 @@ SSR_CACHE_SECS=3600
|
|||||||
|
|
||||||
# Compression algorithms for HTTP responses.
|
# Compression algorithms for HTTP responses.
|
||||||
# Comma-separated list, case-insensitive. Supported: gzip, brotli (or br), deflate, zstd.
|
# Comma-separated list, case-insensitive. Supported: gzip, brotli (or br), deflate, zstd.
|
||||||
# Leave empty or unset to disable compression entirely.
|
# Use "all" to enable everything (default when unset); use "none" or "off" to disable.
|
||||||
COMPRESSION_ALGORITHMS=gzip,brotli,deflate,zstd
|
COMPRESSION_ALGORITHMS=gzip,brotli,deflate,zstd
|
||||||
|
|
||||||
# Image serving cache headers (hardcoded defaults)
|
# Image serving cache headers (hardcoded defaults)
|
||||||
|
|||||||
162
src/main.rs
162
src/main.rs
@ -28,18 +28,42 @@ mod theme;
|
|||||||
mod utils;
|
mod utils;
|
||||||
mod webp;
|
mod webp;
|
||||||
|
|
||||||
/// 根据 COMPRESSION_ALGORITHMS 环境变量构造 CompressionLayer。
|
/// 压缩算法配置。
|
||||||
/// 环境变量为空或未设置时返回 None,表示不启用压缩。
|
|
||||||
#[cfg(feature = "server")]
|
#[cfg(feature = "server")]
|
||||||
fn compression_layer_from_env() -> Option<tower_http::compression::CompressionLayer> {
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
use tower_http::compression::CompressionLayer;
|
struct CompressionAlgorithms {
|
||||||
|
gzip: bool,
|
||||||
|
brotli: bool,
|
||||||
|
deflate: bool,
|
||||||
|
zstd: bool,
|
||||||
|
}
|
||||||
|
|
||||||
let env = std::env::var("COMPRESSION_ALGORITHMS").unwrap_or_default();
|
#[cfg(feature = "server")]
|
||||||
|
impl CompressionAlgorithms {
|
||||||
|
fn all_enabled() -> Self {
|
||||||
|
Self {
|
||||||
|
gzip: true,
|
||||||
|
brotli: true,
|
||||||
|
deflate: true,
|
||||||
|
zstd: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
!self.gzip && !self.brotli && !self.deflate && !self.zstd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 解析 COMPRESSION_ALGORITHMS 环境变量值。
|
||||||
|
/// ""、"none"、"off" 返回 None;"all" 或未识别到任何算法时启用全部。
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
fn parse_compression_algorithms(env: &str) -> Option<CompressionAlgorithms> {
|
||||||
let env = env.trim();
|
let env = env.trim();
|
||||||
if env.is_empty() {
|
if env.is_empty() || env.eq_ignore_ascii_case("none") || env.eq_ignore_ascii_case("off") {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut all = false;
|
||||||
let mut gzip = false;
|
let mut gzip = false;
|
||||||
let mut brotli = false;
|
let mut brotli = false;
|
||||||
let mut deflate = false;
|
let mut deflate = false;
|
||||||
@ -47,6 +71,7 @@ fn compression_layer_from_env() -> Option<tower_http::compression::CompressionLa
|
|||||||
|
|
||||||
for part in env.split(',') {
|
for part in env.split(',') {
|
||||||
match part.trim().to_lowercase().as_str() {
|
match part.trim().to_lowercase().as_str() {
|
||||||
|
"all" => all = true,
|
||||||
"gzip" => gzip = true,
|
"gzip" => gzip = true,
|
||||||
"brotli" | "br" => brotli = true,
|
"brotli" | "br" => brotli = true,
|
||||||
"deflate" => deflate = true,
|
"deflate" => deflate = true,
|
||||||
@ -58,16 +83,39 @@ fn compression_layer_from_env() -> Option<tower_http::compression::CompressionLa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !gzip && !brotli && !deflate && !zstd {
|
if all {
|
||||||
|
return Some(CompressionAlgorithms::all_enabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
let algorithms = CompressionAlgorithms {
|
||||||
|
gzip,
|
||||||
|
brotli,
|
||||||
|
deflate,
|
||||||
|
zstd,
|
||||||
|
};
|
||||||
|
if algorithms.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layer = CompressionLayer::new();
|
Some(algorithms)
|
||||||
layer = layer.gzip(gzip);
|
}
|
||||||
layer = layer.br(brotli);
|
|
||||||
layer = layer.deflate(deflate);
|
/// 根据 COMPRESSION_ALGORITHMS 环境变量构造 CompressionLayer。
|
||||||
layer = layer.zstd(zstd);
|
/// 未设置或设置为 "all" 时启用全部算法;设置为 ""、"none" 或 "off" 时禁用。
|
||||||
Some(layer)
|
#[cfg(feature = "server")]
|
||||||
|
fn compression_layer_from_env() -> Option<tower_http::compression::CompressionLayer> {
|
||||||
|
use tower_http::compression::CompressionLayer;
|
||||||
|
|
||||||
|
let env = std::env::var("COMPRESSION_ALGORITHMS").unwrap_or_else(|_| "all".to_string());
|
||||||
|
let algorithms = parse_compression_algorithms(&env)?;
|
||||||
|
|
||||||
|
Some(
|
||||||
|
CompressionLayer::new()
|
||||||
|
.gzip(algorithms.gzip)
|
||||||
|
.br(algorithms.brotli)
|
||||||
|
.deflate(algorithms.deflate)
|
||||||
|
.zstd(algorithms.zstd),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 根据请求路径和方法决定公开页面的 Cache-Control 头。
|
/// 根据请求路径和方法决定公开页面的 Cache-Control 头。
|
||||||
@ -247,7 +295,7 @@ fn main() {
|
|||||||
|
|
||||||
#[cfg(all(test, feature = "server"))]
|
#[cfg(all(test, feature = "server"))]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::cache_control_for_path;
|
use super::{cache_control_for_path, parse_compression_algorithms, CompressionAlgorithms};
|
||||||
use axum::http::Method;
|
use axum::http::Method;
|
||||||
|
|
||||||
fn cache_value(path: &str, method: Method) -> Option<String> {
|
fn cache_value(path: &str, method: Method) -> Option<String> {
|
||||||
@ -314,4 +362,90 @@ mod tests {
|
|||||||
Some("public, max-age=300, stale-while-revalidate=3600".to_string())
|
Some("public, max-age=300, stale-while-revalidate=3600".to_string())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_all_enables_everything() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("all"),
|
||||||
|
Some(CompressionAlgorithms::all_enabled())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_default_env_is_all() {
|
||||||
|
// 模拟未设置环境变量时的默认值
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("all"),
|
||||||
|
Some(CompressionAlgorithms::all_enabled())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_empty_none_off_disable() {
|
||||||
|
assert_eq!(parse_compression_algorithms(""), None);
|
||||||
|
assert_eq!(parse_compression_algorithms("none"), None);
|
||||||
|
assert_eq!(parse_compression_algorithms("NONE"), None);
|
||||||
|
assert_eq!(parse_compression_algorithms("off"), None);
|
||||||
|
assert_eq!(parse_compression_algorithms("OFF"), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_single_algorithm() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("gzip"),
|
||||||
|
Some(CompressionAlgorithms {
|
||||||
|
gzip: true,
|
||||||
|
brotli: false,
|
||||||
|
deflate: false,
|
||||||
|
zstd: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("br"),
|
||||||
|
Some(CompressionAlgorithms {
|
||||||
|
gzip: false,
|
||||||
|
brotli: true,
|
||||||
|
deflate: false,
|
||||||
|
zstd: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_multiple_algorithms() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("gzip, zstd"),
|
||||||
|
Some(CompressionAlgorithms {
|
||||||
|
gzip: true,
|
||||||
|
brotli: false,
|
||||||
|
deflate: false,
|
||||||
|
zstd: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_case_insensitive_and_whitespace_tolerant() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("GZIP, Brotli, Deflate, Zstd"),
|
||||||
|
Some(CompressionAlgorithms::all_enabled())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms(" gzip , br , deflate , zstd "),
|
||||||
|
Some(CompressionAlgorithms::all_enabled())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compression_unknown_algorithms_are_ignored() {
|
||||||
|
assert_eq!(
|
||||||
|
parse_compression_algorithms("gzip, unknown, lz4"),
|
||||||
|
Some(CompressionAlgorithms {
|
||||||
|
gzip: true,
|
||||||
|
brotli: false,
|
||||||
|
deflate: false,
|
||||||
|
zstd: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user