-
Notifications
You must be signed in to change notification settings - Fork 1
fix: handle gzip-compressed responses in toolbar injection #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The debug toolbar middleware was failing to inject the toolbar HTML into gzip-compressed responses. When Litestar's compression middleware runs before the debug toolbar, the response body is gzip bytes, which cannot be decoded as UTF-8. The middleware silently returned the original body without injection. This fix: - Detects gzip content-encoding header - Decompresses the response body before injection - Injects the toolbar HTML into the decompressed HTML - Returns uncompressed response (strips content-encoding header) This ensures the toolbar is visible when compression is enabled, which is the default in many production-like configurations. Fixes toolbar not appearing on admin pages when compression is enabled. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
71f2cbc to
7f699e0
Compare
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a bug where the debug toolbar failed to appear on pages when gzip compression was enabled. The middleware now detects gzip-compressed responses, decompresses them before injecting the toolbar HTML, and returns an uncompressed response with the toolbar visible.
Key Changes:
- Modified
_inject_toolbarto handle gzip-compressed responses by decompressing before injection - Updated method signature to return a tuple of (body, content_encoding) to track encoding state
- Added logic to strip the
content-encodingheader when returning decompressed responses
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
src/debug_toolbar/litestar/middleware.py |
Added gzip decompression logic to _inject_toolbar method, updated return type to tuple, and modified header handling to strip content-encoding when decompressing |
tests/integration/test_litestar_middleware.py |
Added TestGzipCompression test class with tests for gzip-compressed and uncompressed responses |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@JacobCoffee I've opened a new pull request, #25, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@JacobCoffee I've opened a new pull request, #26, to work on those changes. Once the pull request is ready, I'll request review from you. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@JacobCoffee I've opened a new pull request, #27, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@JacobCoffee I've opened a new pull request, #28, to work on those changes. Once the pull request is ready, I'll request review from you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The `is_gzipped` variable was ambiguous - it initially tracked whether the header indicated gzip encoding, but then was repurposed to track whether decompression succeeded. This made the code harder to understand. Renamed to `decompressed` to explicitly indicate it tracks whether we successfully decompressed the body. This makes the logic clearer: - If decompression succeeds and UTF-8 decoding fails, return the decompressed body with no content-encoding header - If decompression fails and UTF-8 decoding fails, return the original body with the original content-encoding header Addresses feedback: #24 (comment) Co-authored-by: JacobCoffee <45884264+JacobCoffee@users.noreply.github.com>
Co-authored-by: JacobCoffee <45884264+JacobCoffee@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@JacobCoffee I've opened a new pull request, #29, to work on those changes. Once the pull request is ready, I'll request review from you. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@JacobCoffee I've opened a new pull request, #30, to work on those changes. Once the pull request is ready, I'll request review from you. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # 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 |
Copilot
AI
Dec 28, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When decompression succeeds but UTF-8 decoding fails, the code returns decompressed binary data with no content-encoding header. This violates HTTP semantics because the client originally sent Accept-Encoding indicating it can handle compression, but now receives uncompressed binary data. This could break clients that expect the data format they requested. Consider returning the original compressed body with the original content-encoding header when toolbar injection isn't possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot open a new pull request to apply changes based on this feedback
|
@JacobCoffee I've opened a new pull request, #31, to work on those changes. Once the pull request is ready, I'll request review from you. |
Summary
Problem
When Litestar's compression middleware runs before the debug toolbar middleware, the response body is gzip bytes. The
_inject_toolbarmethod tried to decode this as UTF-8, which failed silently, returning the original compressed body without the toolbar injected.This caused the toolbar to not appear on any pages when compression was enabled (which is the default in many production-like configurations).
Solution
content-encoding: gzipheadergzip.decompress()content-encodingheader (return uncompressed)content-lengthheader accordinglyTest plan
TestGzipCompressiontest class with 2 tests🤖 Generated with Claude Code