Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions src/debug_toolbar/litestar/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,30 +485,50 @@ def _inject_toolbar(self, body: bytes, context: RequestContext, content_encoding
Args:
body: The original response body (may be compressed).
context: The request context with collected data.
content_encoding: The content-encoding header value (e.g., "gzip").
content_encoding: The content-encoding header value (e.g., "gzip", "br", "zstd").

Returns:
Tuple of (modified body, content_encoding to use).
If gzip was decompressed, returns uncompressed body with empty encoding.
If compression was handled, returns uncompressed body with empty encoding.
"""
# Handle gzip-compressed responses
# Track whether we successfully decompressed the body
decompressed = False
encodings = [e.strip() for e in content_encoding.lower().split(",")] if content_encoding else []

if "gzip" in encodings:
try:
body = gzip.decompress(body)
decompressed = True
except gzip.BadGzipFile:
# Not valid gzip, try to decode as-is
pass
logger.debug("Invalid gzip data, attempting to decode as-is")

elif "br" in encodings:
try:
import brotli # type: ignore[import-untyped]

body = brotli.decompress(body)
decompressed = True
except ImportError:
logger.debug("Brotli not installed, skipping toolbar injection for br-encoded response")
return body, content_encoding
except Exception:
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The broad exception handler catches all exceptions from brotli decompression. This can mask legitimate programming errors or unexpected issues. Consider catching specific exceptions like brotli.error (if available) to handle only expected decompression failures, while allowing unexpected errors to propagate appropriately.

Suggested change
except Exception:
except brotli.error:

Copilot uses AI. Check for mistakes.
logger.debug("Invalid brotli data, attempting to decode as-is")
Comment on lines +504 to +514
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new brotli decompression support lacks test coverage. The existing TestGzipCompression class demonstrates comprehensive testing patterns (valid compression, invalid data, UTF-8 decoding failures, case-insensitive headers) that should be replicated for brotli. Consider adding similar test cases for br-encoded responses to ensure the decompression logic works correctly and handles edge cases appropriately.

Copilot uses AI. Check for mistakes.

elif "zstd" in encodings:
try:
import zstandard # type: ignore[import-untyped]

dctx = zstandard.ZstdDecompressor()
body = dctx.decompress(body)
decompressed = True
Comment on lines +505 to +522
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The brotli and zstandard libraries are imported inline within a try-except block on every request that uses these compression methods. Consider importing these at the module level with a try-except to set flags (e.g., HAS_BROTLI, HAS_ZSTANDARD), then check those flags before attempting decompression. This would improve performance by avoiding repeated import attempts on every request and make the availability check more efficient.

Copilot uses AI. Check for mistakes.
except ImportError:
logger.debug("zstandard not installed, skipping toolbar injection for zstd-encoded response")
return body, content_encoding
except Exception:
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The broad exception handler catches all exceptions from zstandard decompression. This can mask legitimate programming errors or unexpected issues. Consider catching specific exceptions like zstandard.ZstdError to handle only expected decompression failures, while allowing unexpected errors to propagate appropriately.

Suggested change
except Exception:
except zstandard.ZstdError:

Copilot uses AI. Check for mistakes.
logger.debug("Invalid zstd data, attempting to decode as-is")
Comment on lines +516 to +527
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new zstd decompression support lacks test coverage. The existing TestGzipCompression class demonstrates comprehensive testing patterns (valid compression, invalid data, UTF-8 decoding failures, case-insensitive headers) that should be replicated for zstd. Consider adding similar test cases for zstd-encoded responses to ensure the decompression logic works correctly and handles edge cases appropriately.

Copilot uses AI. Check for mistakes.

try:
html = body.decode("utf-8")
except UnicodeDecodeError:
# Can't decode. If we successfully decompressed gzip, return the
# decompressed body with no content-encoding. Otherwise, return
# the body as-is with the original encoding.
if decompressed:
return body, ""
return body, content_encoding
Expand Down
Loading