Skip to content

fix(connect): rewrite Session to use rebuild_method override#468

Open
tdstein wants to merge 2 commits intomainfrom
fix/sessions-use-rebuild-method
Open

fix(connect): rewrite Session to use rebuild_method override#468
tdstein wants to merge 2 commits intomainfrom
fix/sessions-use-rebuild-method

Conversation

@tdstein
Copy link
Copy Markdown
Collaborator

@tdstein tdstein commented Apr 9, 2026

Summary

Replaces the hand-rolled redirect loop in Session.post (src/posit/connect/sessions.py) with a minimal rebuild_method override on top of requests.Session. The previous implementation reimplemented redirect handling from scratch and silently dropped everything requests.SessionRedirectMixin provides.

What the rewrite restores for free:

  • rebuild_auth — strips Authorization on cross-origin hops (the original CVE behind fix(connect): strip Authorization on cross-origin redirects in custom Session #464)
  • Cookie propagation via extract_cookies_to_jar on every hop
  • response.history for the full redirect chain
  • TooManyRedirects raised instead of silently returning the last 3xx response
  • rebuild_proxies, Referer handling, and streaming semantics
  • allow_redirects=False is no longer forced on every POST

Behavior preserved:

  • preserve_post=True (default) keeps POST across 301/302, matching libcurl CURL_REDIR_POST_301|302.
  • preserve_post=False falls back to the RFC 7231 default (downgrade to GET on 301/302).
  • 303 always downgrades to GET; 307/308 always preserve (both handled by the base class).
  • max_redirects is still accepted on post() and now enforced by requests itself.

Behavior change worth calling out:

  • max_redirects exceeded now raises requests.exceptions.TooManyRedirects instead of returning the last 302 response. The old behavior was surprising and undocumented.

Relationship to other PRs

Test plan

  • 9 tests in tests/posit/connect/test_sessions.py pass, including:
    • new: cross-origin redirect strips Authorization
    • new: same-origin redirect preserves Authorization
    • new: response.history is populated
    • updated: max_redirects exceeded raises TooManyRedirects
  • CI
  • Manual smoke test against a Connect instance that 302s from POST /__api__/v1/tasks style endpoints

Replace the hand-rolled redirect loop in Session.post with a minimal
rebuild_method override. Inheriting from requests.SessionRedirectMixin
restores rebuild_auth (strips Authorization on cross-origin hops),
cookie propagation, response.history, TooManyRedirects, proxy rebuild,
and streaming semantics — all of which the previous implementation
silently dropped.

Supersedes the defensive patch in #464.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
2356 2206 94% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
src/posit/connect/sessions.py 100% 🟢
TOTAL 100% 🟢

updated for commit: 5d5e377 by action🐍

@tdstein tdstein force-pushed the fix/sessions-use-rebuild-method branch from 7637f6a to 5d5e377 Compare April 9, 2026 03:33
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