diff --git a/Cargo.toml b/Cargo.toml index bad05665..932f9c40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/conduwuit-example.toml b/conduwuit-example.toml index 9ad35e3f..b5b4bfe1 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -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. # diff --git a/src/config/mod.rs b/src/config/mod.rs index 9a516db1..e183e4eb 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -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()), ]; diff --git a/src/main.rs b/src/main.rs index 0f772862..1045e12b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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(); }; diff --git a/src/service/globals/client.rs b/src/service/globals/client.rs index a6e5d4cb..2d92435d 100644 --- a/src/service/globals/client.rs +++ b/src/service/globals/client.rs @@ -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 {