Skip to content

Fix problems with callers confused by gzip encoding#2

Open
ropoctl wants to merge 2 commits intoQuixiAI:mainfrom
ropoctl:main
Open

Fix problems with callers confused by gzip encoding#2
ropoctl wants to merge 2 commits intoQuixiAI:mainfrom
ropoctl:main

Conversation

@ropoctl
Copy link
Contributor

@ropoctl ropoctl commented Dec 28, 2025

When caller allows gzip encoding, and the backend sends content-encoding gzip, we either need to recompress, or pop the header for the caller.

nb: multidict is not a new dependency, its already the type aiohttp uses; including that in the uv import shebang for hygiene.

Summary by CodeRabbit

  • Bug Fixes

    • Improved proxy response header handling to drop hop-by-hop headers (e.g., Transfer-Encoding, Content-Encoding) for non-streaming responses, ensuring cleaner and more compliant proxy behavior.
  • Chores

    • Internal configuration and tracing logging improved to aid diagnostics and future header management enhancements.

✏️ Tip: You can customize this high-level summary in your review settings.

When caller allows gzip encoding, and the backend sends content-encoding gzip, we either need to recompress, or pop the header for the caller.
@coderabbitai
Copy link

coderabbitai bot commented Dec 28, 2025

📝 Walkthrough

Walkthrough

Response header handling in the proxy's non-streaming path was changed to use a mutable CIMultiDict for upstream headers and to drop hop-by-hop headers (Transfer-Encoding, Content-Encoding). Multidict and YAML utilities were added and logger usage was extended for config/tracing initialization.

Changes

Cohort / File(s) Summary
Proxy header handling & imports
proxy.py
Add multidict import and use CIMultiDict to wrap upstream response headers in non-streaming responses; remove hop-by-hop headers (Transfer-Encoding, Content-Encoding) before returning; add YAML utility import/usage; extend logger calls for configuration loading and tracing setup

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nudge the headers, soft and slick,

I tuck the hops out, quick quick quick,
YAML whispers, logs aglow,
Mutable maps set traffic's flow,
A rabbit's nod — the proxy's fixed.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: fixing a problem where callers become confused by gzip encoding in responses.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2002971 and 1e37e12.

📒 Files selected for processing (1)
  • proxy.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • proxy.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
proxy.py (1)

290-293: Consider aligning with the streaming path's approach.

The streaming path (lines 232-233) removes these headers using a dict comprehension. For consistency, you could use the same pattern here, though both approaches work correctly.

🔎 Alternative approach matching streaming pattern
-                        mutable_headers = CIMultiDict(upstream_response.headers)
-                        mutable_headers.pop('Transfer-Encoding', None)
-                        mutable_headers.pop('Content-Encoding', None)
-
+                        response_headers = {
+                            key: value
+                            for key, value in upstream_response.headers.items()
+                            if key.lower() not in ['content-length', 'transfer-encoding', 'content-encoding']
+                        }
+
                         return web.Response(
                             status=upstream_response.status,
                             body=response_body,
-                            headers=mutable_headers,
+                            headers=response_headers,
                         )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8edba77 and 2002971.

📒 Files selected for processing (1)
  • proxy.py
🧰 Additional context used
🪛 Ruff (0.14.10)
proxy.py

290-290: Undefined name CIMultiDict

(F821)

🔇 Additional comments (1)
proxy.py (1)

27-27: LGTM!

The yaml import is correctly placed and used for configuration loading.

Comment on lines +290 to +293
mutable_headers = CIMultiDict(upstream_response.headers)
mutable_headers.pop('Transfer-Encoding', None)
mutable_headers.pop('Content-Encoding', None)

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, get an overview of the proxy.py file structure and handler locations
head -300 proxy.py | tail -50

Repository: QuixiAI/VibeLogger

Length of output: 2675


🏁 Script executed:

# Look at the specific section around lines 290-293
sed -n '285,305p' proxy.py

Repository: QuixiAI/VibeLogger

Length of output: 968


🏁 Script executed:

# Check the structure of other handlers mentioned
sed -n '325,345p' proxy.py
sed -n '455,475p' proxy.py
sed -n '620,640p' proxy.py

Repository: QuixiAI/VibeLogger

Length of output: 2644


Apply the same header cleanup to other proxy handlers for consistency.

The fix at lines 290-293 correctly removes Transfer-Encoding and Content-Encoding headers from the Gemini response. However, the same cleanup should be applied to handle_list_models, handle_anthropic_request, and handle_openai_request, which currently pass upstream headers directly without removing these encoding headers. If the gzip encoding issue affects proxied responses, it affects all handlers and should be handled consistently.

🧰 Tools
🪛 Ruff (0.14.10)

290-290: Undefined name CIMultiDict

(F821)

🤖 Prompt for AI Agents
In proxy.py around lines 290-293 and in the handlers handle_list_models,
handle_anthropic_request, and handle_openai_request, the upstream response
headers are currently forwarded as-is; replicate the same header cleanup used at
lines 290-293 by creating a mutable copy of upstream_response.headers, removing
'Transfer-Encoding' and 'Content-Encoding' with pop(..., None), and use that
cleaned headers mapping when constructing the proxied response so all proxy
handlers consistently strip those encoding headers; also handle cases where
upstream_response or headers may be missing before copying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant