feat: make HTTP compression algorithms configurable via COMPRESSION_ALGORITHMS
Some checks failed
CI / check (push) Failing after 6m57s
CI / build (push) Has been skipped

This commit is contained in:
xfy 2026-06-17 16:38:41 +08:00
parent 31d5a99d2a
commit facb75d632
2 changed files with 58 additions and 9 deletions

View File

@ -26,6 +26,11 @@ DB_POOL_SIZE=20
# SSR page cache duration in seconds (default: 3600)
SSR_CACHE_SECS=3600
# Compression algorithms for HTTP responses.
# Comma-separated list, case-insensitive. Supported: gzip, brotli (or br), deflate, zstd.
# Leave empty or unset to disable compression entirely.
COMPRESSION_ALGORITHMS=gzip,brotli,deflate,zstd
# Image serving cache headers (hardcoded defaults)
# Uploaded image assets are served with Cache-Control: public, max-age=31536000, immutable.
# Processed variants (?w=, ?format=, etc.) are cached for 24 hours.

View File

@ -28,6 +28,48 @@ mod theme;
mod utils;
mod webp;
/// 根据 COMPRESSION_ALGORITHMS 环境变量构造 CompressionLayer。
/// 环境变量为空或未设置时返回 None表示不启用压缩。
#[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_default();
let env = env.trim();
if env.is_empty() {
return None;
}
let mut gzip = false;
let mut brotli = false;
let mut deflate = false;
let mut zstd = false;
for part in env.split(',') {
match part.trim().to_lowercase().as_str() {
"gzip" => gzip = true,
"brotli" | "br" => brotli = true,
"deflate" => deflate = true,
"zstd" => zstd = true,
other => tracing::warn!(
"Unknown compression algorithm in COMPRESSION_ALGORITHMS: '{}'",
other
),
}
}
if !gzip && !brotli && !deflate && !zstd {
return None;
}
let mut layer = CompressionLayer::new();
layer = layer.gzip(gzip);
layer = layer.br(brotli);
layer = layer.deflate(deflate);
layer = layer.zstd(zstd);
Some(layer)
}
/// 程序入口
fn main() {
// server feature启动服务端
@ -54,7 +96,6 @@ fn main() {
dioxus::server::serve(|| async move {
use dioxus::server::{axum, DioxusRouterExt, ServeConfig};
use std::time::Duration;
use tower_http::compression::CompressionLayer;
use tower_http::timeout::TimeoutLayer;
use axum::http::StatusCode;
@ -101,13 +142,16 @@ fn main() {
let dioxus_app =
axum::Router::new().serve_dioxus_application(config, router::AppRouter);
// 合并 Dioxus + 压缩/30s 超时中间件
let app_routes = dioxus_app
.layer(CompressionLayer::new())
.layer(TimeoutLayer::with_status_code(
StatusCode::REQUEST_TIMEOUT,
Duration::from_secs(30),
));
// 合并 Dioxus + 可选压缩/30s 超时中间件
let app_routes = if let Some(layer) = compression_layer_from_env() {
dioxus_app.layer(layer)
} else {
dioxus_app
}
.layer(TimeoutLayer::with_status_code(
StatusCode::REQUEST_TIMEOUT,
Duration::from_secs(30),
));
// 静态资源路由:图片文件服务。
// 注意axum 0.8 没有 ConnectInfoLayer且 dioxus::server::serve 不会把
@ -124,7 +168,7 @@ fn main() {
axum::routing::get(|| async { StatusCode::NOT_FOUND }),
);
// 合并upload 路由保持自己独立的 300s 超时app routes 加压缩/30sstatic routes 无任何中间件
// 合并upload 路由保持自己独立的 300s 超时app routes 加可选压缩/30sstatic routes 无任何中间件
let router = upload_route.merge(app_routes).merge(static_routes);
Ok(router)