Repository: litestar-org/litestar

Issue:
Bug: `FileResponse` doesn't set `content-encoding` headers on gzip/brotli compressed files
### Description

When using `StaticFilesConfig` to serve compressed files (think `styles.css.gz`), Litestar will happily serve the file and even properly infer the mimetype, but won't set the correct `content-encoding` header required by the browser.

I will provide a PR with a test.

### URL to code causing the issue

_No response_

### MCVE

_No response_

### Steps to reproduce

_No response_

### Screenshots

```bash
"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"
```


### Logs

_No response_

### Litestar Version

1.51.10

### Platform

- [X] Linux
- [ ] Mac
- [ ] Windows
- [ ] Other (Please specify in the description above)


Discussion:

Resolving patch:
diff --git a/starlite/response/file.py b/starlite/response/file.py
--- a/starlite/response/file.py
+++ b/starlite/response/file.py
@@ -1,6 +1,6 @@
 from email.utils import formatdate
 from inspect import iscoroutine
-from mimetypes import guess_type
+from mimetypes import encodings_map, guess_type
 from typing import (
     TYPE_CHECKING,
     Any,
@@ -38,6 +38,9 @@
     )
     from starlite.types.file_types import FileInfo, FileSystemProtocol
 
+# brotli not supported in 'mimetypes.encodings_map' until py 3.9.
+encodings_map[".br"] = "br"
+
 
 async def async_file_iterator(
     file_path: "PathType", chunk_size: int, adapter: "FileSystemAdapter"
@@ -133,8 +136,11 @@ def __init__(
             file_info: The output of calling ``file_system.info(..)``, equivalent to providing a ``stat_result``.
         """
         if not media_type:
-            mimetype, _ = guess_type(filename) if filename else (None, None)
+            mimetype, content_encoding = guess_type(filename) if filename else (None, None)
             media_type = mimetype or "application/octet-stream"
+            if content_encoding is not None:
+                headers = headers or {}
+                headers.update({"content-encoding": content_encoding})
 
         self.chunk_size = chunk_size
         self.content_disposition_type = content_disposition_type


Test patch:
diff --git a/tests/plugins/piccolo_orm/endpoints.py b/tests/plugins/piccolo_orm/endpoints.py
--- a/tests/plugins/piccolo_orm/endpoints.py
+++ b/tests/plugins/piccolo_orm/endpoints.py
@@ -5,7 +5,7 @@
 from starlite import get, post
 from tests.plugins.piccolo_orm.tables import Concert, RecordingStudio, Venue
 
-studio = cast("RecordingStudio", ModelBuilder.build_sync(RecordingStudio, persist=False))
+studio = ModelBuilder.build_sync(RecordingStudio, persist=False)
 venues = cast("List[Venue]", [ModelBuilder.build_sync(Venue, persist=False) for _ in range(3)])
 
 
diff --git a/tests/static_files/test_file_serving_resolution.py b/tests/static_files/test_file_serving_resolution.py
--- a/tests/static_files/test_file_serving_resolution.py
+++ b/tests/static_files/test_file_serving_resolution.py
@@ -1,6 +1,8 @@
+import gzip
 import mimetypes
 from typing import TYPE_CHECKING
 
+import brotli
 import pytest
 from fsspec.implementations.local import LocalFileSystem
 
@@ -162,6 +164,25 @@ def test_static_files_response_mimetype(tmpdir: "Path", extension: str) -> None:
         assert response.headers["content-type"].startswith(expected_mime_type)
 
 
+@pytest.mark.parametrize("extension", ["gz", "br"])
+def test_static_files_response_encoding(tmp_path: "Path", extension: str) -> None:
+    fn = f"test.js.{extension}"
+    path = tmp_path / fn
+    if extension == "br":
+        compressed_data = brotli.compress(b"content")
+    elif extension == "gz":
+        compressed_data = gzip.compress(b"content")
+    path.write_bytes(compressed_data)  # pyright: ignore
+    static_files_config = StaticFilesConfig(path="/static", directories=[tmp_path])
+    expected_encoding_type = mimetypes.guess_type(fn)[1]
+
+    with create_test_client([], static_files_config=[static_files_config]) as client:
+        response = client.get(f"/static/{fn}")
+        assert expected_encoding_type
+        assert response.status_code == HTTP_200_OK
+        assert response.headers["content-encoding"].startswith(expected_encoding_type)
+
+
 @pytest.mark.parametrize("send_as_attachment,disposition", [(True, "attachment"), (False, "inline")])
 def test_static_files_content_disposition(tmpdir: "Path", send_as_attachment: bool, disposition: str) -> None:
     path = tmpdir.mkdir("static_part").mkdir("static") / "test.txt"  # type: ignore