# 機能設計書 84-カスタムルート（Rewrites/Redirects/Headers）

## 概要

本ドキュメントは、Next.jsにおけるカスタムルート設定（Rewrites、Redirects、Headers）の読み込み・検証・正規化に関する機能設計書である。`next.config.js`で定義されたリライト・リダイレクト・カスタムヘッダーのルール処理を提供する。

### 本機能の処理概要

**業務上の目的・背景**：Webアプリケーションでは、URL構造の変更・レガシーURL対応・セキュリティヘッダー付与・外部サービスへのプロキシなど、柔軟なルーティング制御が必要となる。Next.jsはnext.config.jsでRewrites/Redirects/Headersを宣言的に定義する機能を提供し、コードを変更せずにルーティング挙動をカスタマイズ可能にする。

**機能の利用シーン**：ビルド時にnext.config.jsの`rewrites`、`redirects`、`headers`関数を実行し、ルートルールを構築する。これらのルールはサーバーサイドのRouter Serverで利用され、リクエスト処理時に適用される。

**主要な処理内容**：
1. next.config.jsの`rewrites()`、`redirects()`、`headers()`関数の実行
2. 各ルートルールのバリデーション（source/destination形式、パラメータ整合性）
3. i18n設定に基づくロケール対応ルートの自動生成
4. basePath設定に基づくソース/デスティネーションパスの正規化
5. has/missing条件のバリデーション

**関連システム・外部連携**：Router Server（ルーティング適用）、path-to-regexp（パスパターン解析）

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面を持たない内部ルーティング機構である |

## 機能種別

設定管理 / バリデーション / ルーティング制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | string | Yes | マッチするURLパターン | "/"で始まる文字列、4096文字以下 |
| destination | string | Yes（Rewrite/Redirect） | リライト/リダイレクト先URL | "/"、"http://"、"https://"で始まる文字列 |
| permanent | boolean | Yes（Redirect） | 永続リダイレクトかどうか | statusCodeと排他 |
| statusCode | number | No（Redirect） | リダイレクトステータスコード | 301,302,303,307,308のいずれか |
| headers | Array<{key, value}> | Yes（Header） | 設定するヘッダー | 空でないkey/value文字列配列 |
| basePath | false | No | basePathを無視するか | undefinedまたはfalse |
| locale | false | No | ロケールルーティングを無視するか | undefinedまたはfalse |
| has | RouteHas[] | No | マッチ条件（header/cookie/query/host） | 有効なhas条件 |
| missing | RouteHas[] | No | 不一致条件 | 有効なmissing条件 |

### 入力データソース

- `next.config.js` の `rewrites()`、`redirects()`、`headers()` 関数の戻り値

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| CustomRoutes.headers | Header[] | 処理済みカスタムヘッダールール |
| CustomRoutes.rewrites.beforeFiles | Rewrite[] | ファイルシステムルート前に適用されるリライトルール |
| CustomRoutes.rewrites.afterFiles | Rewrite[] | ファイルシステムルート後に適用されるリライトルール |
| CustomRoutes.rewrites.fallback | Rewrite[] | フォールバックリライトルール |
| CustomRoutes.redirects | Redirect[] | 処理済みリダイレクトルール |

### 出力先

Router Server（リクエスト処理時のルーティング判定）

## 処理フロー

### 処理シーケンス

```
1. redirects関数の実行とバリデーション
   └─ loadRedirects(config)
   └─ checkCustomRoutes(redirects, 'redirect')
   └─ processRoutes(redirects, config, 'redirect')
2. rewrites関数の実行とバリデーション
   └─ loadRewrites(config)
   └─ assetPrefixリライトの自動追加
   └─ beforeFiles/afterFiles/fallbackの分類
   └─ checkCustomRoutes(rewrites, 'rewrite')
   └─ processRoutes(rewrites, config, 'rewrite')
3. headers関数の実行とバリデーション
   └─ loadHeaders(config)
   └─ checkCustomRoutes(headers, 'header')
   └─ processRoutes(headers, config, 'header')
4. i18n対応ルート生成（該当時）
   └─ ロケールプレフィックス付きルートの自動生成
   └─ ドメインロケール対応ルートの生成
5. basePath対応
   └─ source/destinationにbasePathを付加
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[loadRedirects]
    B --> C[checkCustomRoutes - redirect]
    C --> D[processRoutes - redirect]
    D --> E[loadRewrites]
    E --> F{assetPrefixあり?}
    F -->|Yes| G[assetPrefixリライト追加]
    F -->|No| H[checkCustomRoutes - rewrite]
    G --> H
    H --> I[processRoutes - rewrite]
    I --> J[loadHeaders]
    J --> K[checkCustomRoutes - header]
    K --> L[processRoutes - header]
    L --> M[CustomRoutes返却]
    M --> N[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-84-01 | source必須 | すべてのルートにsourceが必須 | 全ルート |
| BR-84-02 | destination必須 | Rewrite/Redirectにはdestinationが必須 | Rewrite/Redirect |
| BR-84-03 | statusCode制約 | Redirectのstatus codeは301,302,303,307,308のいずれか | Redirect |
| BR-84-04 | basePath外リライト | basePath=falseのリライトはhttpまたはhttpsで始まるdestination必須 | basePath=false設定時 |
| BR-84-05 | パラメータ整合性 | destination内のパラメータはsourceまたはhasに含まれる必要がある | Rewrite/Redirect |
| BR-84-06 | i18n自動展開 | locale !== falseの場合、各ロケール用ルートが自動生成される | i18n設定有効時 |
| BR-84-07 | Rewrites3段階 | Rewritesはオブジェクト形式でbeforeFiles/afterFiles/fallbackに分類可能 | Rewrites設定時 |

### 計算ロジック

特になし。

## データベース操作仕様

本機能はデータベースに対する操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | routes配列以外の型が返される | 関数がarray型を返すよう修正 |
| - | Error | sourceが未定義または"/"で始まらない | source形式を修正 |
| - | Error | destinationのパラメータがsource/hasに存在しない | パラメータの整合性を確認 |
| - | Error | sourceの正規表現が4096文字を超える | よりシンプルなパターンに変更 |
| - | Error | has/missing条件の型が不正 | has/missing条件を修正 |

### リトライ仕様

リトライは行わない。バリデーションエラー時はprocess.exit(1)で終了する。

## トランザクション仕様

トランザクション管理は不要。

## パフォーマンス要件

ルートルールの処理はビルド時に1回のみ実行される。通常は数ミリ秒で完了する。

## セキュリティ考慮事項

- リダイレクトのdestinationに外部URLを指定する場合はオープンリダイレクト脆弱性に注意
- headersでセキュリティヘッダー（CSP、HSTS等）を追加可能

## 備考

- output: "export"の場合、rewrites/redirects/headersは自動的には機能しない（警告表示）
- assetPrefixが設定されている場合、自動的にassetPrefix用のリライトルールが追加される

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **10-21行目**: `RouteHas`型（header/cookie/query/host条件） |
| 1-2 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **22-39行目**: `Rewrite`型 |
| 1-3 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **41-53行目**: `Header`型 |
| 1-4 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **56-78行目**: `Redirect`型（permanent/statusCode排他） |
| 1-5 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **489-497行目**: `CustomRoutes`インターフェース |

**読解のコツ**: Redirect型はunion型で、`permanent`と`statusCode`が排他的に定義されている点に注意。

#### Step 2: バリデーション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **146-487行目**: `checkCustomRoutes`関数で全バリデーションを実行 |
| 2-2 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **95-114行目**: `checkRedirect` - リダイレクト固有のバリデーション |
| 2-3 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **116-142行目**: `checkHeader` - ヘッダー固有のバリデーション |

**主要処理フロー**:
- **163-178行目**: ルートタイプ別の許可キー定義
- **228-281行目**: has/missing条件のバリデーション
- **289-295行目**: sourceの形式チェック
- **362-427行目**: destinationパラメータの整合性チェック

#### Step 3: ルート処理と正規化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **499-581行目**: `processRoutes`関数でi18n/basePath対応の正規化 |
| 3-2 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **583-599行目**: `loadRedirects`関数 |
| 3-3 | load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | **601-648行目**: `loadRewrites`関数（assetPrefix自動リライト含む） |

### プログラム呼び出し階層図

```
loadCustomRoutes(config)
    |
    +-- loadRedirects(config)
    |       +-- config.redirects()          # ユーザー定義関数実行
    |       +-- checkCustomRoutes(redirects, 'redirect')
    |       |       +-- checkRedirect()
    |       +-- processRoutes(redirects, config, 'redirect')
    |
    +-- loadRewrites(config)
    |       +-- assetPrefixリライト生成
    |       +-- config.rewrites()           # ユーザー定義関数実行
    |       +-- checkCustomRoutes(rewrites, 'rewrite')
    |       +-- processRoutes(rewrites, config, 'rewrite')
    |
    +-- loadHeaders(config)
            +-- config.headers()            # ユーザー定義関数実行
            +-- checkCustomRoutes(headers, 'header')
            |       +-- checkHeader()
            +-- processRoutes(headers, config, 'header')
```

### データフロー図

```
[入力]                    [処理]                          [出力]

next.config.js           checkCustomRoutes()
  redirects() ─────────▶ processRoutes() ──────▶ CustomRoutes.redirects
  rewrites() ──────────▶ processRoutes() ──────▶ CustomRoutes.rewrites
  headers() ───────────▶ processRoutes() ──────▶ CustomRoutes.headers
                              |
i18n config ───────────────────┘ (ロケール展開)
basePath ──────────────────────┘ (パス正規化)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| load-custom-routes.ts | `packages/next/src/lib/load-custom-routes.ts` | ソース | カスタムルートの読み込み・検証・正規化 |
| try-to-parse-path.ts | `packages/next/src/lib/try-to-parse-path.ts` | ソース | パスパターンの解析 |
| redirect-status.ts | `packages/next/src/lib/redirect-status.ts` | ソース | 許可されるリダイレクトステータスコード |
| router-server.ts | `packages/next/src/server/lib/router-server.ts` | ソース | ルートルールの適用先 |
| escape-regexp.ts | `packages/next/src/shared/lib/escape-regexp.ts` | ソース | 正規表現エスケープ |
