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時間
- マージ済み PR(30日)
- 36
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- 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 が 4 日前に担当しました。 オープンenhancement P2 ready for work T-security
modelcontextprotocol/rust-sdk#1371 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 2 日以内に返信
modelcontextprotocol/rust-sdk の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
swc-project/swc#12576 ·
メンテナーはふだん 1 日以内に返信
-
good first issue gpu serve
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
biomejs/biome#12475 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 80/100
メンテナーはふだん 1 日以内に返信