タラバガニー設計局stalins.clubNOTE/notes/workerd-fetch-redirect-error

workerd の fetch は redirect: "error" を受け付けない

Cloudflare Workers (workerd) の fetchRequestInit.redirect"follow""manual" しか許さない。"error" を渡すと リダイレクトが実際に起きたかどうかとは無関係に、呼び出しの時点で TypeError になる。

TypeError: Invalid redirect value, must be one of "follow" or "manual"
("error" won't be implemented since it does not make sense at the edge;
 use "manual" and check the response status code).

ブラウザや Node の fetch では "error" は「リダイレクトされたら失敗させる」という意味の正当な値なので、そのつもりで書いたコードが Workers では成功経路を一度も通らない。

なぜ気づきにくいか

失敗するのが「リダイレクトが起きたとき」ではなく「毎回」なので、症状は「その fetch が常に失敗する」になる。呼び出し側が try/catch で理由を潰していると、原因の異なる失敗と区別がつかない。

さらに、fetch を注入してテストしている場合、テストダブルが実行環境より緩いとこのバグはテストを素通りする。実装が動かないことを検証している状態になる。ランタイム固有の制約は、テストダブル側にも同じ制約を課して初めてテストで捕まえられる。

対処

redirect: "manual" にして、3xx を自分で判定する。

const response = await fetch(url, { redirect: "manual" });
if (response.status >= 300 && response.status < 400) {
  throw new Error("must not redirect");
}

「リダイレクトを追わない」という意図が要るのは、たとえば取得元 URL と文書内の識別子の一致を要求する取得 (OAuth の Client ID Metadata Document など) で、リダイレクトを追うとどちらの URL が正なのか曖昧になる場面。

出典

  • エラーメッセージは workerd 本番で観測したもの (wrangler tail で捕捉)。Cloudflare の fetch ランタイム API ドキュメント には redirect オプションの記述自体が無く、この制約は明文化されていない。

▸ ノート一覧に戻る