[KOB-52864] Fix proxy framing: strip hop-by-hop headers, recompute Content-Length - #62
Merged
Conversation
…2864) urllib3 was blocking on read because the proxy forwarded Connection: keep-alive without Content-Length or chunked framing. Fix: strip hop-by-hop headers, set Content-Length from actual body, force Connection: close. Verified with session 468672 — driver progresses through 5+ Appium commands cleanly post-fix. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes a hang in the generated Python pytest proxy where clients (urllib3) blocked indefinitely after POST /session because the proxy forwarded Connection: keep-alive from upstream without re-establishing valid framing after rewriting the response body (JSON Wire → W3C). The patch strips hop-by-hop headers, recomputes Content-Length from the actual (possibly rewritten) bytes, and forces Connection: close to keep framing unambiguous.
Changes:
- Added a
HOP_BY_HOP_HEADERSfrozenset (per RFC 7230 §6.1) and filtered the forwarded response headers against it. - Set
Content-Lengthbased on the finalresponse_bodylength and forceConnection: close. - Reordered the response emission so headers are computed before
send_response.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
182
to
+183
| response_headers = {key: val for key, val in response.headers.items() | ||
| if key.lower() != 'content-length'} | ||
| if key.lower() not in HOP_BY_HOP_HEADERS} |
chuong777
approved these changes
May 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Connection: keep-alivewithoutContent-Lengthor chunked framing, causing urllib3 to block indefinitely on response read afterPOST /session.src/templates/python/proxy_server.py: strip hop-by-hop headers (Content-Length, Transfer-Encoding, Connection, Keep-Alive, Proxy-Connection, TE, Trailers, Upgrade) from the upstream response, setContent-Lengthfrom the actual (possibly-rewritten) body bytes, and forceConnection: close./sessionand error responses), so the upstreamContent-Lengthis no longer valid.Linked issue
KOB-52864 — full root-cause analysis and pre/post-fix evidence is in the ticket comments.
Why this is correct
Content-Length.Connection: closekeeps framing unambiguous for a single-request-per-connection proxy and avoids keep-alive reuse hazards when upstream and downstream framings disagree.Verification
POST /wd/hub/session 200; zero further Appium commands; Kobiton ended the session withstate: TIMEOUT,endReason: USER-408,endMessage: \"Force end session by idling time out\"after 16m 12.7s.POST /appium/settings,POST /context,POST /timeouts, then 5+ recorded test commands (POST /execute/sync,POST /element,GET .../displayed, etc.) before hitting a separate XPath-locator issue tracked as KOB-52937. CleanDELETE /session 200on teardown.Test plan
Content-Lengthset to the post-rewrite body lengthConnection: closeappears in forwarded response headers🤖 Generated with Claude Code