Streamable HTTP client: update the stored endpoint URI after a 308
Maintainer thường phản hồi trong vòng 2 ngày
@connor4312 đang làm issue này rồi.
Từ ngày 16/10/2026.
Đánh giá
Issue này chưa được đánh giá.
Mô tả
Follow-up from #1203 and #1367.
Problem
After #1367, the default Streamable HTTP client follows same-origin 307 and 308 redirects. But it never saves the new location. Every request still goes to the configured URI first and gets redirected again.
A 308 means the move is permanent, so the client could send later requests straight to the new URI.
Current behavior
At a156be8, the URI lives in StreamableHttpClientTransportConfig::uri. The worker clones the config once and never changes it. Each request copies the URI from there:
- POST:
post_request, and the initialize POSTs at startup and in the fallback path. - Standalone GET stream: resumption with
Last-Event-IDuses its own copy inStreamableHttpClientReconnect. - SSE on a POST response: resumption gets a copy too.
- Re-initialization after a 404:
perform_reinitialization. - DELETE on close:
SessionCleanupInfoholds its own copy, used at exit.
All of these requests use the same reqwest::Client, so the redirect policy applies to GET and DELETE too, not only POST.
reqwest gives us the final URL through Response::url(), but not the status of each hop. The Policy::custom closure sees each hop's status. However, one policy is shared by every request on the client, and it can't tell which request a hop belongs to.
Proposal
- Only save the new URI when every hop in the chain is a 308. If any hop is a 307, keep the configured URI.
- Have the
runloop keep the current URI, since it already owns the session state. Use that URI for new POSTs, new GET streams, re-initialization and the DELETE. - Return the final URL from the client to the worker.
StreamableHttpPostResponsedoesn't carry a URL today.
To find out whether every hop was a 308, we could:
- Stop on 308 in the policy and follow it by hand in the reqwest
StreamableHttpClientimpl, with the same origin and hop-limit checks. - Record hops from the policy closure into shared state. This is unreliable when concurrent requests start from the same URI.
Open questions
- Same-origin is already enforced, so only the path and query can change. Do we need any other check?
- Should the session ID carry over to the new URI, or should the client re-initialize?
- OAuth:
AuthorizationManagerkeeps its ownbase_url. It's the fallbackresource, and the protected resource metadataresourceis checked against it. If the transport URI moves andbase_urldoesn't, they no longer match, and there's no way to updatebase_urltoday. Should we skip the update whenAuthClientwraps the transport, or move both? - Requests and streams already in flight keep the old URI. Is that fine, or should resumption pick up the new one?
- Default client only, or also clients passed to
with_client?
Related
- #1203: the original redirect report
- #1367: follows same-origin 307/308 in the default client
- The TypeScript and Python SDKs don't update the stored URL either. Both follow same-origin redirects and keep the configured URL (TypeScript, Python).
- Ngôn ngữ chính
- Rust
- Star
- 4k
- Fork
- 688
- Merge trung bình
- 3 ngày 11 giờ
- Pull request đã merge (30 ngày)
- 36
Chuẩn bị môi trường
Khởi chạy dev container của dự án ngay trên trình duyệt, bằng tài khoản GitHub của bạn.
- Không có Dockerfile hay tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của modelcontextprotocol/rust-sdk
-
Streamable HTTP client: a 401 or 403 with a JSON-RPC error body and no WWW-Authenticate loses its HTTP statusCó thể đã có người làm @aton-of-data đã nhận 8 ngày trước. Đang mởbug P2 ready for work T-security T-transport
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
modelcontextprotocol/rust-sdk#1339 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
auth: refresh_token() requests offline_access that was never granted, so refreshes fail with invalid_scopeCó thể đã có người làm @jstar0 đã nhận 11 ngày trước. Đang mởbug P1 ready for work T-security T-transport
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
modelcontextprotocol/rust-sdk#1330 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
P3 question Stale T-documentation T-enhancement
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 86/100
modelcontextprotocol/rust-sdk#1155 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 2 ngày
-
outputSchema is generated for the deserialize contract; tool results are serialisedCó thể đã có người làm @connor4312 đã nhận 3 ngày trước. Đang mởbug P2 ready for work T-handler
modelcontextprotocol/rust-sdk#1374 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Expose OAuth discovery and registration results for application-owned flowsCó thể đã có người làm @connor4312 đã nhận 4 ngày trước. Đang mởenhancement P2 ready for work T-security
modelcontextprotocol/rust-sdk#1371 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của modelcontextprotocol/rust-sdk
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
swc-project/swc#12576 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue gpu serve
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
biomejs/biome#12475 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 80/100
Maintainer thường phản hồi trong vòng 1 ngày