定義
自分のドメインの /blog を開いたらブラウザが「リダイレクトが多すぎます」で諦めた、しかしアプリのコードにはリダイレクトが一行もない — そんな経験があるならこの概念が必要だ。
rewrite はアドレスバーをそのままにして サーバーが代わりにアップストリームから取得してくる、つまりプロキシである。リダイレクト(3xx 応答)はブラウザに「別の場所へ行け」と伝えるものだ。落とし穴は、rewrite がアップストリームの応答を加工しないという点にある。アップストリームが 3xx を返せば、その 3xx がそのままブラウザに渡る。アップストリームが自分のドメインへ正規化し返す SaaS だった場合、カスタムドメインと配信元の間を永遠に往復することになる。
なぜ必要か
ブログ・ドキュメント・ステータスページだけを SaaS に任せつつ、自分のドメインのサブパスに見せる構成はごく一般的だ。rewrite を単に「裏で静かに取得してくるもの」と理解していると、3xx の素通しを予測できない。
多くの SaaS は SEO 上の URL 重複を避けるため、テナントのアドレス(saas.com/<tenant>)に来たリクエストを顧客の正規ドメイン(mydomain.com/blog)へ 308 で移動させる。しかしその正規ドメインは rewrite で SaaS を指し返すので、リクエストは回り続ける。症状は ERR_TOO_MANY_REDIRECTS で、リポジトリのどこにもリダイレクトが存在しないため原因を追いにくい。
動作原理
- ブラウザが
https://mydomain.com/blogをリクエストする。 - アプリのサーバーが rewrite 規則に従って
https://saas.com/tenantへ サーバー間リクエスト を行う。 - SaaS は正規化ポリシーに従い
308 Location: https://mydomain.com/blogを返す。 - rewrite はプロキシなので、その 308 が そのまま ブラウザに渡る。
- ブラウザは
Locationに従って手順 1 へ戻る — 無限ループ。
| 観点 | リダイレクト | rewrite |
|---|---|---|
| アドレスバー | 変わる | 変わらない |
| 応答 | 自分で 3xx を生成 | アップストリームの応答を中継 |
| アップストリームの 3xx | 該当なし | そのまま素通し |
| ループの危険 | 規則が循環したとき | アップストリームが自分を指し返すとき |
実務適用
まず、宛先がプロキシ可能かを推測ではなく確認する。
curl -I --max-redirs 0 https://saas.com/tenant
# HTTP/2 308
# location: https://mydomain.com/blog ← 自分を指し返す = ループ確定
curl -I --max-redirs 0 https://proxy.saas.dev/tenant
# HTTP/2 200 ← プロキシ先として適切
多くの SaaS ベンダーは、カスタムドメイン向けに正規化しない別ホストを用意している。rewrite の宛先をそちらに向ける。
// next.config.mjs
async rewrites() {
return {
afterFiles: [
{ source: "/blog", destination: "https://proxy.saas.dev/tenant" },
{ source: "/blog/:path*", destination: "https://proxy.saas.dev/tenant/:path*" },
],
};
}
同じ設定ファイル内で既に正常動作している兄弟規則 があるなら、その宛先ホストが答えであることが多い。壊れた規則だけを睨まず、隣の行を読む。
トレードオフ
- rewrite(プロキシ): パスが自分のドメインに統一され、SEO・Cookie・解析が一つのオリジンに揃う。代わりに全トラフィックが自分のサーバーを通るためレイテンシとコストが増え、アップストリームのヘッダーやステータスコードを引き受けることになる。
- サブドメインの CNAME 委譲(
blog.mydomain.com→ SaaS): プロキシコストゼロでループも起きないが、コンテンツが別ホストに置かれ Cookie と解析が分断される。 - リダイレクト: 最も単純だが、SaaS のアドレスが利用者に露出する。
使ってはいけない場合
- アップストリームが正規化を行い、ベンダーがプロキシ専用ホストを提供していない場合。rewrite を諦めてサブドメイン委譲にする。
/robots.txtや/sitemap.xmlのようなサイト全体のリソースをサブサービスへプロキシする場合。ブログの robots がサイト全体のインデックス方針を上書きしてしまう。- アップストリームが自分のドメイン向けに認証 Cookie を発行する場合 — プロキシ経由では Cookie のドメインが一致せずセッションが壊れる。
よくある間違い
- rewrite をリダイレクトとして読む ことで、アップストリームの 3xx が素通しされる点を見落とす。ループの大半はここから始まる。
- 他人の設定スニペットを丸ごと貼る。 必要だったのは宛先ホスト一行なのに、全体を適用すると既存のキャッチオール rewrite や画像・バンドラー設定が黙って消え、サイト全体が落ちる。
- 理由なく規則を
beforeFilesに移す。 同じパスにローカルのルートがなければ挙動はafterFilesと同じで、差分が大きくなり優先順位のバグを招くだけだ。 - ブラウザキャッシュに騙される。 308 は恒久的でキャッシュされる。修正の確認はシークレットウィンドウか
curlで行う。
関連概念
- ssrf-url-fetch-proxy-guard — サーバーが他人の URL を取得するときの宛先検証
- locale-aware-i18n-routing — パスルーティングと rewrite が重なる層
- etag-conditional-request-304 — プロキシ越しの条件付き応答