config options for HTTP compression on tower+reqwest

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-03-30 00:47:26 -04:00 committed by June
parent 44435f76fe
commit f818c368c0
5 changed files with 93 additions and 17 deletions

View file

@ -293,7 +293,7 @@ hyperlocal = { git = "https://github.com/softprops/hyperlocal", rev = "2ee4d1496
[features]
default = ["conduit_bin", "backend_rocksdb", "systemd", "element_hacks", "sentry_telemetry"]
default = ["conduit_bin", "backend_rocksdb", "systemd", "element_hacks", "sentry_telemetry", "gzip_compression", "brotli_compression"]
conduit_bin = ["axum"]
backend_sqlite = ["sqlite"]
backend_rocksdb = ["rocksdb"]
@ -306,7 +306,6 @@ sentry_telemetry = ["sentry", "sentry-tracing", "sentry-tower"]
gzip_compression = ["tower-http/compression-gzip", "reqwest/gzip"]
zstd_compression = ["tower-http/compression-zstd"]
brotli_compression = ["tower-http/compression-br", "reqwest/brotli"]
#all_compression = ["tower-http/compression-full"] # all compression algos
sha256_media = ["sha2"]
io_uring = ["rust-rocksdb/io-uring"]

View file

@ -104,11 +104,25 @@ max_request_size = 20_000_000 # in bytes
# Set this to true for conduwuit to compress HTTP response bodies using zstd.
# This option does nothing if conduwuit was not built with `zstd_compression` feature.
# Please be aware that enabling HTTP compression may weaken or even defeat TLS.
# Please be aware that enabling HTTP compression may weaken TLS.
# Most users should not need to enable this.
# See https://breachattack.com/ and https://wikipedia.org/wiki/BREACH before deciding to enable this.
zstd_compression = false
# Set this to true for conduwuit to compress HTTP response bodies using gzip.
# This option does nothing if conduwuit was not built with `gzip_compression` feature.
# Please be aware that enabling HTTP compression may weaken TLS.
# Most users should not need to enable this.
# See https://breachattack.com/ and https://wikipedia.org/wiki/BREACH before deciding to enable this.
gzip_compression = false
# Set this to true for conduwuit to compress HTTP response bodies using brotli.
# This option does nothing if conduwuit was not built with `brotli_compression` feature.
# Please be aware that enabling HTTP compression may weaken TLS.
# Most users should not need to enable this.
# See https://breachattack.com/ and https://wikipedia.org/wiki/BREACH before deciding to enable this.
brotli_compression = false
# Vector list of IPv4 and IPv6 CIDR ranges / subnets *in quotes* that you do not want conduwuit to send outbound requests to.
# Defaults to RFC1918, unroutable, loopback, multicast, and testnet addresses for security.
#

View file

@ -197,6 +197,10 @@ pub struct Config {
#[serde(default)]
pub zstd_compression: bool,
#[serde(default)]
pub gzip_compression: bool,
#[serde(default)]
pub brotli_compression: bool,
#[serde(default)]
pub allow_guest_registration: bool,
@ -453,8 +457,12 @@ impl fmt::Display for Config {
}
&lst.into_iter().join(", ")
}),
#[cfg(feature = "compression-zstd")]
("zstd Response Body Compression", &self.zstd_compression.to_string()),
#[cfg(feature = "zstd_compression")]
("Zstd HTTP Compression", &self.zstd_compression.to_string()),
#[cfg(feature = "gzip_compression")]
("Gzip HTTP Compression", &self.gzip_compression.to_string()),
#[cfg(feature = "brotli_compression")]
("Brotli HTTP Compression", &self.brotli_compression.to_string()),
#[cfg(feature = "rocksdb")]
("RocksDB database log level", &self.rocksdb_log_level),
#[cfg(feature = "rocksdb")]
@ -529,8 +537,11 @@ impl fmt::Display for Config {
&self.allow_check_for_updates.to_string(),
),
("Enable netburst on startup", &self.startup_netburst.to_string()),
#[cfg(feature = "sentry_telemetry")]
("Sentry.io reporting and tracing", &self.sentry.to_string()),
#[cfg(feature = "sentry_telemetry")]
("Sentry.io send server_name in logs", &self.sentry_send_server_name.to_string()),
#[cfg(feature = "sentry_telemetry")]
("Sentry.io tracing sample rate", &self.sentry_traces_sample_rate.to_string()),
];

View file

@ -293,23 +293,47 @@ async fn run_server() -> io::Result<()> {
.expect("failed to convert max request size"),
));
let app;
#[cfg(any(feature = "zstd_compresion", feature = "gzip_compression", feature = "brotli_compression"))]
let mut compression_layer = tower_http::compression::CompressionLayer::new();
#[allow(clippy::unnecessary_operation)] // error[E0658]: attributes on expressions are experimental
#[cfg(feature = "zstd_compression")]
{
app = if cfg!(feature = "zstd_compression") && config.zstd_compression {
debug!("zstd body compression is enabled");
routes()
.layer(middlewares.compression())
.into_make_service()
if config.zstd_compression {
compression_layer = compression_layer.zstd(true);
} else {
routes().layer(middlewares).into_make_service()
}
compression_layer = compression_layer.no_zstd();
};
};
#[allow(clippy::unnecessary_operation)] // error[E0658]: attributes on expressions are experimental
#[cfg(not(feature = "zstd_compression"))]
#[cfg(feature = "gzip_compression")]
{
if config.gzip_compression {
compression_layer = compression_layer.gzip(true);
} else {
compression_layer = compression_layer.no_gzip();
};
};
#[cfg(feature = "brotli_compression")]
{
if config.brotli_compression {
compression_layer = compression_layer.br(true);
} else {
compression_layer = compression_layer.no_br();
};
};
let app;
#[cfg(any(feature = "zstd_compresion", feature = "gzip_compression", feature = "brotli_compression"))]
{
app = routes()
.layer(compression_layer)
.layer(middlewares)
.into_make_service();
};
#[cfg(not(any(feature = "zstd_compresion", feature = "gzip_compression", feature = "brotli_compression")))]
{
app = routes().layer(middlewares).into_make_service();
};

View file

@ -88,7 +88,7 @@ impl Client {
None => env!("CARGO_PKG_VERSION").to_owned(),
};
let builder = reqwest::Client::builder()
let mut builder = reqwest::Client::builder()
.hickory_dns(true)
.timeout(Duration::from_secs(config.request_timeout))
.connect_timeout(Duration::from_secs(config.request_conn_timeout))
@ -97,6 +97,34 @@ impl Client {
.user_agent("Conduwuit".to_owned() + "/" + &version)
.redirect(redirect::Policy::limited(6));
#[cfg(feature = "gzip_compression")]
{
builder = if config.gzip_compression {
builder.gzip(true)
} else {
builder.gzip(false).no_gzip()
};
};
#[cfg(feature = "brotli_compression")]
{
builder = if config.brotli_compression {
builder.brotli(true)
} else {
builder.brotli(false).no_brotli()
};
};
#[cfg(not(feature = "gzip_compression"))]
{
builder = builder.no_gzip();
}
#[cfg(not(feature = "brotli_compression"))]
{
builder = builder.no_brotli();
}
if let Some(proxy) = config.proxy.to_proxy()? {
Ok(builder.proxy(proxy))
} else {