Node.js の fetch でリダイレクトが処理される流れを追う
前置き
この記事では、Node.jsでfetchでリダイレクトが発生した際に、最終的なレスポンスを取得できる仕組みを紹介します。(本記事では低レイヤの実装については踏み込みません)
実際の動作
検証に利用するサイト
検証には httpbin.org を利用します。このサイトでは、https://httpbin.org/redirect/{n}にアクセスすると、n-1のURLにリダイレクトされます。https://httpbin.org/redirect/1からはhttps://httpbin.org/getにリダイレクトされ、以下のようなJSONを返します
{
"args": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "ja,en-US;q=0.9,en;q=0.8",
"Host": "httpbin.org",
"Priority": "u=0, i",
"Sec-Ch-Ua": "\"Chromium\";v=\"140\", \"Not=A?Brand\";v=\"24\", \"Google Chrome\";v=\"140\"",
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": "\"macOS\"",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-68c7df48-047fce2c44ee4efa2b864286"
},
"origin": "175.177.48.22",
"url": "https://httpbin.org/get"
}
また、curl -iでhttps://httpbin.org/redirect/1叩くと、302リダイレクトのレスポンスが返ることが確認できます。
$ curl -i https://httpbin.org/redirect/1
HTTP/2 302
date: Mon, 15 Sep 2025 09:53:43 GMT
content-type: text/html; charset=utf-8
content-length: 215
server: gunicorn/19.9.0
location: /get
access-control-allow-origin: *
access-control-allow-credentials: true
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/get">/get</a>. If not click the link.%
Node.jsでの実行結果
それではコードとその実行結果を確認してみます。
コード:
const res = await fetch("https://httpbin.org/redirect/1");
console.log(await res.text());
実行結果:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "br, gzip, deflate",
"Accept-Language": "*",
"Host": "httpbin.org",
"Sec-Fetch-Mode": "cors",
"User-Agent": "node",
"X-Amzn-Trace-Id": "Root=1-68c7e13a-45737a1033105b8e6135fda7"
},
"origin": "175.177.48.22",
"url": "https://httpbin.org/get"
}
この結果から、Node.js の fetch はリダイレクトを自動的に処理してくれていることが分かります。
Node.jsの実装
それでは、この挙動がどのようにNode.jsで実装されているかを確認していきます。Node.jsのfetchは内部的にundiciというライブラリに依存しています。fetchのエントリーポイントはこの行になります。
このfetchからfetchingが呼ばれます。
さらにこのfetchingからmainFetchが呼ばれ、
httpFetchが呼ばれます。httpFetchの以下の部分でレスポンスを取得しています。(本記事ではこれ以上の深掘りは行いません)
そして、httpFetchの以下の部分でリダイレクトの処理を行っています。
redirectStatusSetはHTTPの仕様に基づいた値が設定されています。
ここでは、リクエスト時にリダイレクトモードがmanualであり(errorまたはfollowでない、かつHTTPステータスコードが30x系の場合にhttpRedirectFetchが呼ばれるようになっています。このhttpRedirectFetchからはLocationで指定されたURLでmainFetchが呼ばれるので、fetchはリダイレクトした値を取得できるようになっています。
実装まとめ
-
fetch→fetching→mainFetch→httpFetchの順に処理が進む -
httpFetchでレスポンスを取得する - レスポンスのステータスコードが リダイレクト対象 (30x 系) であれば
httpRedirectFetchが呼ばれる -
httpRedirectFetchではLocationヘッダーの URL を使って再度mainFetchを実行する
まとめ
Node.jsのfetchではHTTPステータスコードに応じて再リクエストを行うので、リダイレクト先のレスポンスを取得できるという仕組みでした!
Discussion