Streamable HTTP client: update the stored endpoint URI after a 308
维护者通常 2 天内回复
@connor4312 已经在做这个了。
开始于 2026年10月16日。
评估
这个 Issue 还没有评估数据。
描述
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).
- 主要语言
- Rust
- 星标
- 4k
- 派生
- 688
- 平均合并
- 3 天 11 小时
- 30 天内合并 PR
- 36
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
modelcontextprotocol/rust-sdk 的其他 Issue
-
Streamable HTTP client: a 401 or 403 with a JSON-RPC error body and no WWW-Authenticate loses its HTTP status可能已有人在做 @aton-of-data 于 8 天前认领。 未关闭bug P2 ready for work T-security T-transport
难度 2/5 1-3 小时 新手友好度 68/100
modelcontextprotocol/rust-sdk#1339 ·
维护者通常 2 天内回复
-
auth: refresh_token() requests offline_access that was never granted, so refreshes fail with invalid_scope可能已有人在做 @jstar0 于 11 天前认领。 未关闭bug P1 ready for work T-security T-transport
难度 2/5 1-3 小时 新手友好度 65/100
modelcontextprotocol/rust-sdk#1330 ·
维护者通常 2 天内回复
-
P3 question Stale T-documentation T-enhancement
难度 1/5 1 小时以内 新手友好度 86/100
modelcontextprotocol/rust-sdk#1155 · 1 条评论 ·
维护者通常 2 天内回复
-
outputSchema is generated for the deserialize contract; tool results are serialised可能已有人在做 @connor4312 于 3 天前认领。 未关闭bug P2 ready for work T-handler
modelcontextprotocol/rust-sdk#1374 · 2 条评论 · 已指派 1 人 ·
维护者通常 2 天内回复
-
Expose OAuth discovery and registration results for application-owned flows可能已有人在做 @connor4312 于 3 天前认领。 未关闭enhancement P2 ready for work T-security
modelcontextprotocol/rust-sdk#1371 · 1 条评论 · 已指派 1 人 ·
维护者通常 2 天内回复
查看 modelcontextprotocol/rust-sdk 的全部 Issue
相似的 Issue
-
documentation
难度 2/5 1-3 小时 新手友好度 78/100
charles-hood/DiagramCraft#73 ·
-
难度 1/5 1-3 小时 新手友好度 78/100
ontologyportal/sigma-rs#200 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
chipsalliance/caliptra-sw#4311 ·
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
`image_generation`: `max_retries` is ignored for OpenAI-compatible providers (always 2 retries)可能已有人在做 @ericz7900 今天认领。 未关闭llm translation
难度 2/5 1-3 小时 新手友好度 77/100
维护者通常 1 天内回复