Repository: static-web-server/static-web-server (language: rust)

Issue:
Fails to compile without compression feature
### Search for duplicate issues

- [X] I already searched, and this issue is not a duplicate.

### Issue scope

Libary (crate)

### Describe the bug

As things are right now, static-web-server cannot be used if the `compression` feature is disabled. Both disabling compression completely and using a specific feature that only enables one compression algorithm will result in compile errors.

### How to reproduce it

1. Create a Rust project.
2. Run `cargo add static-web-server --no-default-features --features compression-gzip` from the command line.
3. Run `cargo build` from the command line.

Compilation fails due to following errors:

```
error[E0609]: no field `compression` on type `cli::General`
  --> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/static-web-server-2.28.0/src/testing.rs:31:39
   |
31 |             compression: opts.general.compression,
   |                                       ^^^^^^^^^^^ unknown field
   |
   = note: available fields are: `host`, `port`, `fd`, `threads_multiplier`, `max_blocking_threads` ... and 19 others

error[E0609]: no field `compression_static` on type `cli::General`
  --> ~.cargo/registry/src/index.crates.io-6f17d22bba15001f/static-web-server-2.28.0/src/testing.rs:32:46
   |
32 |             compression_static: opts.general.compression_static,
   |                                              ^^^^^^^^^^^^^^^^^^ unknown field
   |
   = note: available fields are: `host`, `port`, `fd`, `threads_multiplier`, `max_blocking_threads` ... and 19 others
```

That’s because `handler::RequestHandlerOpts` has the `compression` and `compression_static` fields unconditionally, yet in `cli::General` these fields depend on the `compression` feature.

This makes it impossible to disable compression or to select individual compression algorithms in the builds – it always has to be all three of them.

### Expected behavior

The project’s dependencies should compile successfully, both when compression features are disabled and when only one compression algorithm is enabled.

### Complementary information

_No response_

### Build target

x86_64-unknown-linux-gnu

### Environment and specs

- [ ] **static-web-server:** 2.28.0
- [ ] **OS:** Fedora 39
- [ ] **Arch:** x86_64


### Additional context

_No response_


Discussion / hints:
Good catch! Yes, we should be able to compile without the `compression`. That's the whole point of using the Cargo compression features.



Fix patch:
diff --git a/src/compression.rs b/src/compression.rs
index 0c509ff8..50cee2dc 100644
--- a/src/compression.rs
+++ b/src/compression.rs
@@ -8,13 +8,13 @@
 
 // Part of the file is borrowed from <https://github.com/seanmonstar/warp/pull/513>*
 
-#[cfg(feature = "compression-brotli")]
+#[cfg(any(feature = "compression", feature = "compression-brotli"))]
 use async_compression::tokio::bufread::BrotliEncoder;
-#[cfg(feature = "compression-deflate")]
+#[cfg(any(feature = "compression", feature = "compression-deflate"))]
 use async_compression::tokio::bufread::DeflateEncoder;
-#[cfg(feature = "compression-gzip")]
+#[cfg(any(feature = "compression", feature = "compression-gzip"))]
 use async_compression::tokio::bufread::GzipEncoder;
-#[cfg(feature = "compression-zstd")]
+#[cfg(any(feature = "compression", feature = "compression-zstd"))]
 use async_compression::tokio::bufread::ZstdEncoder;
 
 use bytes::Bytes;
@@ -61,7 +61,7 @@ pub const TEXT_MIME_TYPES: [&str; 24] = [
 ];
 
 /// Create a wrapping handler that compresses the Body of a [`hyper::Response`]
-/// using `gzip`, `deflate`, `brotli` or `zstd` if is specified in the `Accept-Encoding` header, adding
+/// using gzip, `deflate`, `brotli` or `zstd` if is specified in the `Accept-Encoding` header, adding
 /// `content-encoding: <coding>` to the Response's [`HeaderMap`].
 /// It also provides the ability to apply compression for text-based MIME types only.
 pub fn auto(
@@ -76,6 +76,11 @@ pub fn auto(
 
     // Compress response based on Accept-Encoding header
     if let Some(encoding) = get_prefered_encoding(headers) {
+        tracing::trace!(
+            "prefered encoding selected from the accept-ecoding header: {:?}",
+            encoding
+        );
+
         // Skip compression for non-text-based MIME types
         if let Some(content_type) = resp.headers().typed_get::<ContentType>() {
             let mime = Mime::from(content_type);
@@ -84,29 +89,31 @@ pub fn auto(
             }
         }
 
-        #[cfg(feature = "compression-gzip")]
+        #[cfg(any(feature = "compression", feature = "compression-gzip"))]
         if encoding == ContentCoding::GZIP {
             let (head, body) = resp.into_parts();
             return Ok(gzip(head, body.into()));
         }
 
-        #[cfg(feature = "compression-deflate")]
+        #[cfg(any(feature = "compression", feature = "compression-deflate"))]
         if encoding == ContentCoding::DEFLATE {
             let (head, body) = resp.into_parts();
             return Ok(deflate(head, body.into()));
         }
 
-        #[cfg(feature = "compression-brotli")]
+        #[cfg(any(feature = "compression", feature = "compression-brotli"))]
         if encoding == ContentCoding::BROTLI {
             let (head, body) = resp.into_parts();
             return Ok(brotli(head, body.into()));
         }
 
-        #[cfg(feature = "compression-zstd")]
+        #[cfg(any(feature = "compression", feature = "compression-zstd"))]
         if encoding == ContentCoding::ZSTD {
             let (head, body) = resp.into_parts();
             return Ok(zstd(head, body.into()));
         }
+
+        tracing::trace!("no compression feature matched the prefered encoding, probably not enabled or unsupported");
     }
 
     Ok(resp)
@@ -114,13 +121,16 @@ pub fn auto(
 
 /// Create a wrapping handler that compresses the Body of a [`Response`].
 /// using gzip, adding `content-encoding: gzip` to the Response's [`HeaderMap`].
-#[cfg(feature = "compression-gzip")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression-gzip")))]
+#[cfg(any(feature = "compression", feature = "compression-gzip"))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(feature = "compression", feature = "compression-gzip")))
+)]
 pub fn gzip(
     mut head: http::response::Parts,
     body: CompressableBody<Body, hyper::Error>,
 ) -> Response<Body> {
-    tracing::trace!("compressing response body on the fly using gzip");
+    tracing::trace!("compressing response body on the fly using GZIP");
 
     let body = Body::wrap_stream(ReaderStream::new(GzipEncoder::new(StreamReader::new(body))));
     let header = create_encoding_header(head.headers.remove(CONTENT_ENCODING), ContentCoding::GZIP);
@@ -131,13 +141,16 @@ pub fn gzip(
 
 /// Create a wrapping handler that compresses the Body of a [`Response`].
 /// using deflate, adding `content-encoding: deflate` to the Response's [`HeaderMap`].
-#[cfg(feature = "compression-deflate")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression-deflate")))]
+#[cfg(any(feature = "compression", feature = "compression-deflate"))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(feature = "compression", feature = "compression-deflate")))
+)]
 pub fn deflate(
     mut head: http::response::Parts,
     body: CompressableBody<Body, hyper::Error>,
 ) -> Response<Body> {
-    tracing::trace!("compressing response body on the fly using deflate");
+    tracing::trace!("compressing response body on the fly using DEFLATE");
 
     let body = Body::wrap_stream(ReaderStream::new(DeflateEncoder::new(StreamReader::new(
         body,
@@ -153,13 +166,16 @@ pub fn deflate(
 
 /// Create a wrapping handler that compresses the Body of a [`Response`].
 /// using brotli, adding `content-encoding: br` to the Response's [`HeaderMap`].
-#[cfg(feature = "compression-brotli")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression-brotli")))]
+#[cfg(any(feature = "compression", feature = "compression-brotli"))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(feature = "compression", feature = "compression-brotli")))
+)]
 pub fn brotli(
     mut head: http::response::Parts,
     body: CompressableBody<Body, hyper::Error>,
 ) -> Response<Body> {
-    tracing::trace!("compressing response body on the fly using brotli");
+    tracing::trace!("compressing response body on the fly using BROTLI");
 
     let body = Body::wrap_stream(ReaderStream::new(BrotliEncoder::new(StreamReader::new(
         body,
@@ -173,13 +189,16 @@ pub fn brotli(
 
 /// Create a wrapping handler that compresses the Body of a [`Response`].
 /// using zstd, adding `content-encoding: zstd` to the Response's [`HeaderMap`].
-#[cfg(feature = "compression-zstd")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression-zstd")))]
+#[cfg(any(feature = "compression", feature = "compression-zstd"))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(feature = "compression", feature = "compression-zstd")))
+)]
 pub fn zstd(
     mut head: http::response::Parts,
     body: CompressableBody<Body, hyper::Error>,
 ) -> Response<Body> {
-    tracing::trace!("compressing response body on the fly using zstd");
+    tracing::trace!("compressing response body on the fly using ZSTD");
 
     let body = Body::wrap_stream(ReaderStream::new(ZstdEncoder::new(StreamReader::new(body))));
     let header = create_encoding_header(head.headers.remove(CONTENT_ENCODING), ContentCoding::ZSTD);
@@ -203,7 +222,46 @@ pub fn create_encoding_header(existing: Option<HeaderValue>, coding: ContentCodi
 #[inline(always)]
 pub fn get_prefered_encoding(headers: &HeaderMap<HeaderValue>) -> Option<ContentCoding> {
     if let Some(ref accept_encoding) = headers.typed_get::<AcceptEncoding>() {
-        return accept_encoding.prefered_encoding();
+        tracing::trace!("request with accept-ecoding header: {:?}", accept_encoding);
+
+        let encoding = accept_encoding.prefered_encoding();
+        if let Some(prefered_enc) = encoding {
+            let mut feature_formats = Vec::<ContentCoding>::with_capacity(5);
+            if cfg!(feature = "compression-deflate") {
+                feature_formats.push(ContentCoding::DEFLATE);
+            }
+            if cfg!(feature = "compression-gzip") {
+                feature_formats.push(ContentCoding::GZIP);
+            }
+            if cfg!(feature = "compression-brotli") {
+                feature_formats.push(ContentCoding::BROTLI);
+            }
+            if cfg!(feature = "compression-zstd") {
+                feature_formats.push(ContentCoding::ZSTD);
+            }
+
+            // If there is only one Cargo compression feature enabled
+            // then re-evaluate the prefered encoding and return
+            // that feature compression algorithm as `ContentCoding` only
+            // if was contained in the `AcceptEncoding` value.
+            if feature_formats.len() == 1 {
+                let feature_enc = *feature_formats.first().unwrap();
+                if feature_enc != prefered_enc
+                    && accept_encoding
+                        .sorted_encodings()
+                        .any(|enc| enc == feature_enc)
+                {
+                    tracing::trace!(
+                        "prefered encoding {:?} is re-evalated to {:?} because is the only compression feature enabled that matches the `accept-encoding` header",
+                        prefered_enc,
+                        feature_enc
+                    );
+                    return Some(feature_enc);
+                }
+            }
+
+            return encoding;
+        }
     }
     None
 }
diff --git a/src/compression_static.rs b/src/compression_static.rs
index f24195f3..e087d7e8 100644
--- a/src/compression_static.rs
+++ b/src/compression_static.rs
@@ -38,13 +38,13 @@ pub async fn precompressed_variant<'a>(
     // Determine prefered-encoding extension if available
     let comp_ext = match compression::get_prefered_encoding(headers) {
         // https://zlib.net/zlib_faq.html#faq39
-        #[cfg(feature = "compression-gzip")]
+        #[cfg(any(feature = "compression", feature = "compression-gzip"))]
         Some(ContentCoding::GZIP | ContentCoding::DEFLATE) => "gz",
         // https://peazip.github.io/brotli-compressed-file-format.html
-        #[cfg(feature = "compression-brotli")]
+        #[cfg(any(feature = "compression", feature = "compression-brotli"))]
         Some(ContentCoding::BROTLI) => "br",
         // https://datatracker.ietf.org/doc/html/rfc8878
-        #[cfg(feature = "compression-zstd")]
+        #[cfg(any(feature = "compression", feature = "compression-zstd"))]
         Some(ContentCoding::ZSTD) => "zst",
         _ => {
             tracing::trace!(
diff --git a/src/handler.rs b/src/handler.rs
index 08a7c99a..d497d94e 100644
--- a/src/handler.rs
+++ b/src/handler.rs
@@ -10,7 +10,13 @@ use headers::{ContentType, HeaderMap, HeaderMapExt, HeaderValue};
 use hyper::{Body, Request, Response, StatusCode};
 use std::{future::Future, net::IpAddr, net::SocketAddr, path::PathBuf, sync::Arc};
 
-#[cfg(feature = "compression")]
+#[cfg(any(
+    feature = "compression",
+    feature = "compression-gzip",
+    feature = "compression-brotli",
+    feature = "compression-zstd",
+    feature = "compression-deflate"
+))]
 use crate::compression;
 
 #[cfg(feature = "basic-auth")]
@@ -457,7 +463,13 @@ impl RequestHandler {
                     }
 
                     // Compression content encoding varies so use a `Vary` header
-                    #[cfg(feature = "compression")]
+                    #[cfg(any(
+                        feature = "compression",
+                        feature = "compression-gzip",
+                        feature = "compression-brotli",
+                        feature = "compression-zstd",
+                        feature = "compression-deflate"
+                    ))]
                     if self.opts.compression || compression_static {
                         resp.headers_mut().append(
                             hyper::header::VARY,
@@ -466,7 +478,13 @@ impl RequestHandler {
                     }
 
                     // Auto compression based on the `Accept-Encoding` header
-                    #[cfg(feature = "compression")]
+                    #[cfg(any(
+                        feature = "compression",
+                        feature = "compression-gzip",
+                        feature = "compression-brotli",
+                        feature = "compression-zstd",
+                        feature = "compression-deflate"
+                    ))]
                     if self.opts.compression && !_is_precompressed {
                         resp = match compression::auto(method, headers, resp) {
                             Ok(res) => res,
@@ -526,7 +544,13 @@ impl RequestHandler {
                         }
 
                         // Compression content encoding varies so use a `Vary` header
-                        #[cfg(feature = "compression")]
+                        #[cfg(any(
+                            feature = "compression",
+                            feature = "compression-gzip",
+                            feature = "compression-brotli",
+                            feature = "compression-zstd",
+                            feature = "compression-deflate"
+                        ))]
                         if self.opts.compression || compression_static {
                             resp.headers_mut().append(
                                 hyper::header::VARY,
@@ -535,7 +559,13 @@ impl RequestHandler {
                         }
 
                         // Auto compression based on the `Accept-Encoding` header
-                        #[cfg(feature = "compression")]
+                        #[cfg(any(
+                            feature = "compression",
+                            feature = "compression-gzip",
+                            feature = "compression-brotli",
+                            feature = "compression-zstd",
+                            feature = "compression-deflate"
+                        ))]
                         if self.opts.compression {
                             resp = match compression::auto(method, headers, resp) {
                                 Ok(res) => res,
diff --git a/src/lib.rs b/src/lib.rs
index 4f601a95..7e546645 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -111,11 +111,41 @@ extern crate serde;
 #[cfg(feature = "basic-auth")]
 #[cfg_attr(docsrs, doc(cfg(feature = "basic-auth")))]
 pub mod basic_auth;
-#[cfg(feature = "compression")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+#[cfg(any(
+    feature = "compression",
+    feature = "compression-gzip",
+    feature = "compression-brotli",
+    feature = "compression-zstd",
+    feature = "compression-deflate"
+))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    )))
+)]
 pub mod compression;
-#[cfg(feature = "compression")]
-#[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+#[cfg(any(
+    feature = "compression",
+    feature = "compression-gzip",
+    feature = "compression-brotli",
+    feature = "compression-zstd",
+    feature = "compression-deflate"
+))]
+#[cfg_attr(
+    docsrs,
+    doc(cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    )))
+)]
 pub mod compression_static;
 pub mod control_headers;
 pub mod cors;
diff --git a/src/server.rs b/src/server.rs
index a6b96745..172315a6 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -217,21 +217,67 @@ impl Server {
         let security_headers = general.security_headers;
         server_info!("security headers: enabled={}", security_headers);
 
-        // Auto compression based on the `Accept-Encoding` header
-        #[cfg(not(feature = "compression"))]
+        #[cfg(not(any(
+            feature = "compression",
+            feature = "compression-deflate",
+            feature = "compression-gzip",
+            feature = "compression-deflate",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+        )))]
         let compression = false;
-        #[cfg(feature = "compression")]
+        // Auto compression based on the `Accept-Encoding` header
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-deflate",
+            feature = "compression-gzip",
+            feature = "compression-deflate",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+        ))]
         let compression = general.compression;
-        #[cfg(feature = "compression")]
-        server_info!("auto compression: enabled={}", compression);
+
+        #[allow(unused_mut)]
+        let mut compression_formats = Vec::<&str>::with_capacity(5);
+        #[cfg(any(feature = "compression", feature = "compression-deflate"))]
+        compression_formats.push("deflate");
+        #[cfg(any(feature = "compression", feature = "compression-gzip"))]
+        compression_formats.push("gzip");
+        #[cfg(any(feature = "compression", feature = "compression-brotli"))]
+        compression_formats.push("brotli");
+        #[cfg(any(feature = "compression", feature = "compression-zstd"))]
+        compression_formats.push("zstd");
+        let compression_format = compression_formats.join(",");
+        server_info!(
+            "auto compression: enabled={}, formats={}",
+            compression,
+            compression_format
+        );
 
         // Check pre-compressed files based on the `Accept-Encoding` header
-        #[cfg(not(feature = "compression"))]
+        #[cfg(not(any(
+            feature = "compression",
+            feature = "compression-deflate",
+            feature = "compression-gzip",
+            feature = "compression-deflate",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+        )))]
         let compression_static = false;
-        #[cfg(feature = "compression")]
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-deflate",
+            feature = "compression-gzip",
+            feature = "compression-deflate",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+        ))]
         let compression_static = general.compression_static;
-        #[cfg(feature = "compression")]
-        server_info!("compression static: enabled={}", compression_static);
+        server_info!(
+            "compression static: enabled={}, formats={}",
+            compression_static,
+            compression_format
+        );
 
         // Directory listing options
         #[cfg(feature = "directory-listing")]
diff --git a/src/settings/cli.rs b/src/settings/cli.rs
index 60f912ec..a05cc9e2 100644
--- a/src/settings/cli.rs
+++ b/src/settings/cli.rs
@@ -229,8 +229,23 @@ pub struct General {
     /// Files are checked in the specified order.
     pub index_files: String,
 
-    #[cfg(feature = "compression")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    ))]
+    #[cfg_attr(
+        docsrs,
+        doc(cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))
+    )]
     #[arg(
         long,
         short = 'x',
@@ -243,9 +258,23 @@ pub struct General {
     )]
     /// Gzip, Deflate, Brotli or Zstd compression on demand determined by the Accept-Encoding header and applied to text-based web file types only.
     pub compression: bool,
-
-    #[cfg(feature = "compression")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    ))]
+    #[cfg_attr(
+        docsrs,
+        doc(cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))
+    )]
     #[arg(
         long,
         default_value = "false",
diff --git a/src/settings/file.rs b/src/settings/file.rs
index 19e3bf09..72d99099 100644
--- a/src/settings/file.rs
+++ b/src/settings/file.rs
@@ -135,13 +135,43 @@ pub struct General {
     pub cache_control_headers: Option<bool>,
 
     /// Compression.
-    #[cfg(feature = "compression")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    ))]
+    #[cfg_attr(
+        docsrs,
+        doc(cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))
+    )]
     pub compression: Option<bool>,
 
     /// Check for a pre-compressed file on disk.
-    #[cfg(feature = "compression")]
-    #[cfg_attr(docsrs, doc(cfg(feature = "compression")))]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-gzip",
+        feature = "compression-brotli",
+        feature = "compression-zstd",
+        feature = "compression-deflate"
+    ))]
+    #[cfg_attr(
+        docsrs,
+        doc(cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))
+    )]
     pub compression_static: Option<bool>,
 
     /// Error 404 pages.
diff --git a/src/settings/mod.rs b/src/settings/mod.rs
index 1ec7bdad..d9907ddd 100644
--- a/src/settings/mod.rs
+++ b/src/settings/mod.rs
@@ -98,9 +98,21 @@ impl Settings {
         let mut config_file = opts.config_file.clone();
         let mut cache_control_headers = opts.cache_control_headers;
 
-        #[cfg(feature = "compression")]
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        ))]
         let mut compression = opts.compression;
-        #[cfg(feature = "compression")]
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        ))]
         let mut compression_static = opts.compression_static;
 
         let mut page404 = opts.page404;
@@ -189,11 +201,23 @@ impl Settings {
                 if let Some(v) = general.cache_control_headers {
                     cache_control_headers = v
                 }
-                #[cfg(feature = "compression")]
+                #[cfg(any(
+                    feature = "compression",
+                    feature = "compression-gzip",
+                    feature = "compression-brotli",
+                    feature = "compression-zstd",
+                    feature = "compression-deflate"
+                ))]
                 if let Some(v) = general.compression {
                     compression = v
                 }
-                #[cfg(feature = "compression")]
+                #[cfg(any(
+                    feature = "compression",
+                    feature = "compression-gzip",
+                    feature = "compression-brotli",
+                    feature = "compression-zstd",
+                    feature = "compression-deflate"
+                ))]
                 if let Some(v) = general.compression_static {
                     compression_static = v
                 }
@@ -511,9 +535,21 @@ impl Settings {
                 log_level,
                 config_file,
                 cache_control_headers,
-                #[cfg(feature = "compression")]
+                #[cfg(any(
+                    feature = "compression",
+                    feature = "compression-gzip",
+                    feature = "compression-brotli",
+                    feature = "compression-zstd",
+                    feature = "compression-deflate"
+                ))]
                 compression,
-                #[cfg(feature = "compression")]
+                #[cfg(any(
+                    feature = "compression",
+                    feature = "compression-gzip",
+                    feature = "compression-brotli",
+                    feature = "compression-zstd",
+                    feature = "compression-deflate"
+                ))]
                 compression_static,
                 page404,
                 page50x,
diff --git a/src/static_files.rs b/src/static_files.rs
index 1103eee5..059d5fbd 100644
--- a/src/static_files.rs
+++ b/src/static_files.rs
@@ -27,7 +27,14 @@ use crate::{
     http_ext::{MethodExt, HTTP_SUPPORTED_METHODS},
 };
 
-#[cfg(feature = "compression")]
+#[cfg(any(
+    feature = "compression",
+    feature = "compression-deflate",
+    feature = "compression-gzip",
+    feature = "compression-deflate",
+    feature = "compression-brotli",
+    feature = "compression-zstd"
+))]
 use crate::compression_static;
 
 #[cfg(feature = "directory-listing")]
@@ -248,7 +255,14 @@ async fn get_composed_file_metadata<'a>(
                     file_path.push(index);
 
                     // Pre-compressed variant check for the autoindex
-                    #[cfg(feature = "compression")]
+                    #[cfg(any(
+                        feature = "compression",
+                        feature = "compression-deflate",
+                        feature = "compression-gzip",
+                        feature = "compression-deflate",
+                        feature = "compression-brotli",
+                        feature = "compression-zstd"
+                    ))]
                     if _compression_static {
                         if let Some(p) =
                             compression_static::precompressed_variant(file_path, _headers).await
@@ -289,7 +303,14 @@ async fn get_composed_file_metadata<'a>(
                 }
             } else {
                 // Fallback pre-compressed variant check for the specific file
-                #[cfg(feature = "compression")]
+                #[cfg(any(
+                    feature = "compression",
+                    feature = "compression-deflate",
+                    feature = "compression-gzip",
+                    feature = "compression-deflate",
+                    feature = "compression-brotli",
+                    feature = "compression-zstd"
+                ))]
                 if _compression_static {
                     if let Some(p) =
                         compression_static::precompressed_variant(file_path, _headers).await
@@ -313,7 +334,14 @@ async fn get_composed_file_metadata<'a>(
         }
         Err(err) => {
             // Pre-compressed variant check for the file not found
-            #[cfg(feature = "compression")]
+            #[cfg(any(
+                feature = "compression",
+                feature = "compression-deflate",
+                feature = "compression-gzip",
+                feature = "compression-deflate",
+                feature = "compression-brotli",
+                feature = "compression-zstd"
+            ))]
             if _compression_static {
                 if let Some(p) =
                     compression_static::precompressed_variant(file_path, _headers).await
@@ -333,7 +361,14 @@ async fn get_composed_file_metadata<'a>(
             let new_meta: Option<Metadata>;
             (file_path, new_meta) = suffix_file_html_metadata(file_path);
 
-            #[cfg(feature = "compression")]
+            #[cfg(any(
+                feature = "compression",
+                feature = "compression-deflate",
+                feature = "compression-gzip",
+                feature = "compression-deflate",
+                feature = "compression-brotli",
+                feature = "compression-zstd"
+            ))]
             match new_meta {
                 Some(new_meta) => {
                     return Ok(FileMetadata {


Test patch:
diff --git a/src/testing.rs b/src/testing.rs
index ef27a7e3..3288be12 100644
--- a/src/testing.rs
+++ b/src/testing.rs
@@ -26,10 +26,43 @@ pub mod fixtures {
         std::env::set_var("SERVER_CONFIG_FILE", f);
         let opts = Settings::get(false).unwrap();
 
+        #[cfg(not(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))]
+        let compression = false;
+        #[cfg(not(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        )))]
+        let compression_static = false;
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        ))]
+        let compression = opts.general.compression;
+        #[cfg(any(
+            feature = "compression",
+            feature = "compression-gzip",
+            feature = "compression-brotli",
+            feature = "compression-zstd",
+            feature = "compression-deflate"
+        ))]
+        let compression_static = opts.general.compression_static;
+
         let req_handler_opts = RequestHandlerOpts {
             root_dir: opts.general.root,
-            compression: opts.general.compression,
-            compression_static: opts.general.compression_static,
+            compression,
+            compression_static,
             #[cfg(feature = "directory-listing")]
             dir_listing: opts.general.directory_listing,
             #[cfg(feature = "directory-listing")]
diff --git a/tests/compression_static.rs b/tests/compression_static.rs
index ebf691ae..5610c759 100644
--- a/tests/compression_static.rs
+++ b/tests/compression_static.rs
@@ -3,7 +3,14 @@
 #![deny(rust_2018_idioms)]
 #![deny(dead_code)]
 
-#[cfg(feature = "compression")]
+#[cfg(any(
+    feature = "compression",
+    feature = "compression-deflate",
+    feature = "compression-gzip",
+    feature = "compression-deflate",
+    feature = "compression-brotli",
+    feature = "compression-zstd"
+))]
 #[cfg(test)]
 mod tests {
     use bytes::Bytes;
@@ -45,7 +52,14 @@ mod tests {
             #[cfg(feature = "directory-listing")]
             dir_listing_format: &DirListFmt::Html,
             redirect_trailing_slash: true,
-            #[cfg(feature = "compression")]
+            #[cfg(any(
+                feature = "compression",
+                feature = "compression-deflate",
+                feature = "compression-gzip",
+                feature = "compression-deflate",
+                feature = "compression-brotli",
+                feature = "compression-zstd"
+            ))]
             compression_static: true,
             ignore_hidden_files: false,
             index_files: &[],
@@ -105,7 +119,14 @@ mod tests {
             #[cfg(feature = "directory-listing")]
             dir_listing_format: &DirListFmt::Html,
             redirect_trailing_slash: true,
-            #[cfg(feature = "compression")]
+            #[cfg(any(
+                feature = "compression",
+                feature = "compression-deflate",
+                feature = "compression-gzip",
+                feature = "compression-deflate",
+                feature = "compression-brotli",
+                feature = "compression-zstd"
+            ))]
             compression_static: true,
             ignore_hidden_files: false,
             index_files: &[],
diff --git a/tests/static_files.rs b/tests/static_files.rs
index 4fc022c4..f3e9abe1 100644
--- a/tests/static_files.rs
+++ b/tests/static_files.rs
@@ -11,7 +11,14 @@ mod tests {
     use std::fs;
     use std::path::PathBuf;
 
-    #[cfg(feature = "compression")]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-deflate",
+        feature = "compression-gzip",
+        feature = "compression-deflate",
+        feature = "compression-brotli",
+        feature = "compression-zstd"
+    ))]
     use static_web_server::compression;
 
     #[cfg(feature = "directory-listing")]
@@ -654,7 +661,14 @@ mod tests {
         }
     }
 
-    #[cfg(feature = "compression")]
+    #[cfg(any(
+        feature = "compression",
+        feature = "compression-deflate",
+        feature = "compression-gzip",
+        feature = "compression-deflate",
+        feature = "compression-brotli",
+        feature = "compression-zstd"
+    ))]
     #[tokio::test]
     async fn handle_file_compressions() {
         let encodings = ["gzip", "deflate", "br", "zstd", "xyz"];