# 機能設計書 73-NextResponse

## 概要

本ドキュメントは、Next.jsのNextResponseクラスの設計について記述する。NextResponseはWeb標準のResponse APIを拡張し、Middleware内でリダイレクト・リライト・Cookie操作・ヘッダー操作を行うための静的メソッドと追加プロパティを提供するクラスである。

### 本機能の処理概要

NextResponseクラスは、Web標準の`Response`クラスを継承し、Middlewareのレスポンス生成に必要な4つの静的メソッド（`json`, `redirect`, `rewrite`, `next`）を提供する。また、`cookies`プロパティを通じてResponseCookiesの操作（Set-Cookieヘッダーの管理）を行い、`x-middleware-*`内部ヘッダーを通じてRouter Serverにリライト・リダイレクト等の指示を伝達する。

**業務上の目的・背景**：Middleware内でのレスポンス操作は、Web標準のResponse APIだけでは十分にサポートされていない。特にNext.js固有のリライト（内部的なURL書き換え）やリクエストヘッダーの上書きは、独自の内部ヘッダープロトコルが必要である。NextResponseはこれらを抽象化し、開発者がシンプルなAPIでMiddlewareのレスポンスを制御できるようにする。

**機能の利用シーン**：Middlewareでのリダイレクト応答生成、URLリライト指示、JSONレスポンスの返却、Cookie設定・削除、リクエストヘッダーの上書き指示、次のMiddlewareまたはルートハンドラへの処理引き渡し。

**主要な処理内容**：
1. `NextResponse.redirect(url, status)` - HTTPリダイレクトレスポンスの生成（Locationヘッダー設定）
2. `NextResponse.rewrite(destination, init)` - URLリライト指示の生成（x-middleware-rewriteヘッダー設定）
3. `NextResponse.next(init)` - 後続処理への引き渡し（x-middleware-nextヘッダー設定）
4. `NextResponse.json(body, init)` - JSONレスポンスの生成
5. `cookies`プロパティ - ResponseCookiesプロキシによるCookie操作（x-middleware-set-cookieヘッダーとの同期）

**関連システム・外部連携**：Middleware、Router Server（内部ヘッダー通信）、NextURL、ResponseCookies（@edge-runtime/cookies）

**権限による制御**：特になし。NextResponseはMiddlewareのレスポンス生成ユーティリティとして動作する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | NextResponseは画面に直接関連しない。Middlewareのレスポンス生成に使用される |

## 機能種別

レスポンス生成 / ルーティング制御

## 入力仕様

### 入力パラメータ

#### コンストラクタ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| body | BodyInit \| null | No | レスポンスボディ | - |
| init | ResponseInit | No | レスポンス初期化オプション（headers, status, statusText, url, nextConfig） | - |

#### redirect()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | string \| NextURL \| URL | Yes | リダイレクト先URL | validateURL()で検証 |
| init | number \| ResponseInit | No | ステータスコードまたは初期化オプション | ステータスは301/302/303/307/308のみ |

#### rewrite()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| destination | string \| NextURL \| URL | Yes | リライト先URL | validateURL()で検証 |
| init | MiddlewareResponseInit | No | 初期化オプション（headersとrequest.headersを含む） | request.headersはHeadersインスタンスであること |

### 入力データソース

Middlewareハンドラ関数内でのプログラマティックな呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| cookies | ResponseCookies | Set-Cookieヘッダーを管理するCookieオブジェクト |
| status | number | HTTPステータスコード（Responseから継承） |
| headers | Headers | レスポンスヘッダー。x-middleware-*内部ヘッダーを含む |
| body | ReadableStream \| null | レスポンスボディ（Responseから継承） |

### 出力先

Router Serverが内部ヘッダーを解釈し、適切なルーティング処理を実行する。

## 処理フロー

### 処理シーケンス

```
1. 静的メソッド呼び出し（redirect/rewrite/next/json）
   └─ 各メソッド固有のヘッダー設定
2. Headersオブジェクトの構築
   └─ redirect: Locationヘッダー設定
   └─ rewrite: x-middleware-rewriteヘッダー設定
   └─ next: x-middleware-nextヘッダー設定
3. handleMiddlewareField（rewrite/nextのみ）
   └─ init.request.headersが指定されている場合、x-middleware-request-*ヘッダーに変換
   └─ x-middleware-override-headersにキー一覧を設定
4. NextResponseインスタンスの生成
   └─ コンストラクタでResponseCookiesプロキシを設定
5. ResponseCookiesプロキシ（set/delete時）
   └─ Cookie操作後にx-middleware-set-cookieヘッダーを同期更新
```

### フローチャート

```mermaid
flowchart TD
    A{静的メソッド種別} -->|redirect| B[Locationヘッダー設定]
    A -->|rewrite| C[x-middleware-rewrite設定]
    A -->|next| D[x-middleware-next設定]
    A -->|json| E[Response.json呼び出し]
    B --> F{ステータスコード検証}
    F -->|有効| G[NextResponse生成]
    F -->|無効| H[RangeError]
    C --> I[handleMiddlewareField]
    D --> I
    I --> J{request.headers指定?}
    J -->|Yes| K[x-middleware-request-* ヘッダー設定]
    K --> L[x-middleware-override-headers設定]
    L --> G
    J -->|No| G
    E --> G
    G --> M[ResponseCookiesプロキシ構築]
    M --> N[NextResponseインスタンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-73-01 | リダイレクトステータス制限 | redirect()のステータスコードは301,302,303,307,308のみ。デフォルト307 | redirect()使用時 |
| BR-73-02 | Cookie同期 | cookies.set()/delete()時にx-middleware-set-cookieヘッダーが自動同期される | Cookie操作時 |
| BR-73-03 | リクエストヘッダー上書き | init.request.headersが指定された場合、x-middleware-request-*ヘッダーとx-middleware-override-headersが設定される | rewrite()/next()でrequest.headers指定時 |
| BR-73-04 | URL検証必須 | redirect()とrewrite()のURL引数はvalidateURL()で検証される | redirect()/rewrite()使用時 |

### 計算ロジック

特になし。

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

### 操作別データベース影響一覧

NextResponseクラスはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| RangeError | 範囲エラー | redirect()で無効なステータスコードを指定 | 301/302/303/307/308を使用 |
| Error | 型エラー | request.headersがHeadersインスタンスでない場合 | Headersインスタンスを渡す |
| Error | URL不正 | 不正なURL文字列をredirect()/rewrite()に渡した場合 | 絶対URLを使用 |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ResponseCookiesプロキシは操作時に毎回x-middleware-set-cookieヘッダーを再構築する
- 静的メソッドは軽量なオブジェクト生成のみで高速に動作する

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

- x-middleware-*ヘッダーはNext.js内部通信用であり、外部からの不正な操作を防止する必要がある
- Cookie操作はhttpOnly, secure, sameSite等のセキュリティ属性をサポートする

## 備考

- `NextResponse<Body>`はジェネリック型パラメータを持ち、`json()`メソッドでの型推論に使用される
- INTERNALSプロパティにはオプショナルなurl（NextURL）とbody（Body型）も保持される
- MiddlewareResponseInitインターフェースのrequestフィールドでリクエストヘッダーの上書きが可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | response.ts | `packages/next/src/server/web/spec-extension/response.ts` | INTERNALSの構造（cookies, url?, body?）、REDIRECTSセット（301,302,303,307,308）、ResponseInit/MiddlewareResponseInitインターフェースを確認 |
| 1-2 | cookies.ts | `packages/next/src/server/web/spec-extension/cookies.ts` | ResponseCookies, stringifyCookieの再エクスポート元を確認 |

**読解のコツ**: `handleMiddlewareField()`関数はリクエストヘッダー上書きの内部プロトコルを実装している。`x-middleware-request-{key}`ヘッダーと`x-middleware-override-headers`ヘッダーの組み合わせでRouter Server側にヘッダー上書きを指示する仕組みを理解することが重要。

#### Step 2: 静的メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | response.ts | `packages/next/src/server/web/spec-extension/response.ts` | json(109-115), redirect(117-133), rewrite(135-144), next(146-152)の各静的メソッドの実装を確認 |

**主要処理フロー**:
1. **109-115行目**: `json()` - Response.jsonを呼び出しNextResponseでラップ
2. **117-133行目**: `redirect()` - ステータスコード検証、Locationヘッダー設定、空ボディでNextResponse生成
3. **135-144行目**: `rewrite()` - x-middleware-rewriteヘッダー設定、handleMiddlewareField呼び出し
4. **146-152行目**: `next()` - x-middleware-nextヘッダー設定、handleMiddlewareField呼び出し

#### Step 3: ResponseCookiesプロキシを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | response.ts | `packages/next/src/server/web/spec-extension/response.ts` | コンストラクタ（43-87行目）内のProxy構築。set/delete時のx-middleware-set-cookieヘッダー同期ロジックを確認 |

**主要処理フロー**:
- **49-76行目**: cookiesプロキシのget trapでset/deleteメソッドをインターセプトし、操作後にstringifyCookieでx-middleware-set-cookieヘッダーを更新

#### Step 4: 利用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | adapter.ts | `packages/next/src/server/web/adapter.ts` | adapter()関数内でNextResponseが使用される箇所。特に484行目のデフォルトNextResponse.next()生成を確認 |

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

```
NextResponse (static methods)
    |
    +-- NextResponse.redirect(url, init)
    |       +-- validateURL() [utils.ts]
    |       +-- new NextResponse(null, {headers, status})
    |
    +-- NextResponse.rewrite(destination, init)
    |       +-- validateURL() [utils.ts]
    |       +-- handleMiddlewareField(init, headers) [response.ts:12]
    |       +-- new NextResponse(null, {headers})
    |
    +-- NextResponse.next(init)
    |       +-- handleMiddlewareField(init, headers) [response.ts:12]
    |       +-- new NextResponse(null, {headers})
    |
    +-- NextResponse.json(body, init)
    |       +-- Response.json(body, init) [Web API]
    |       +-- new NextResponse(response.body, response)
    |
    +-- new NextResponse(body, init) [constructor]
            +-- super(body, init) [Response]
            +-- new ResponseCookies(headers) [cookies.ts]
            +-- new Proxy(cookies) [cookiesProxy]
            +-- new NextURL(init.url) [optional]
```

### データフロー図

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

url/destination -----> NextResponse静的メソッド        NextResponseインスタンス
body (optional)            |                                |
init (optional)            +-> ヘッダー設定                  +-- headers
                           |   (Location /                       (x-middleware-rewrite /
                           |    x-middleware-rewrite /             x-middleware-next /
                           |    x-middleware-next)                 Location /
                           |                                      x-middleware-set-cookie /
                           +-> handleMiddlewareField              x-middleware-override-headers)
                           |   (x-middleware-request-*       +-- cookies (ResponseCookies)
                           |    x-middleware-override-headers)+-- status
                           |                                 +-- body
                           +-> ResponseCookies Proxy
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| response.ts | `packages/next/src/server/web/spec-extension/response.ts` | ソース | NextResponseクラス本体 |
| cookies.ts | `packages/next/src/server/web/spec-extension/cookies.ts` | ソース | ResponseCookies, stringifyCookieの再エクスポート |
| reflect.ts | `packages/next/src/server/web/spec-extension/adapters/reflect.ts` | ソース | ReflectAdapterユーティリティ |
| next-url.ts | `packages/next/src/server/web/next-url.ts` | ソース | NextURLクラス |
| utils.ts | `packages/next/src/server/web/utils.ts` | ソース | validateURL関数 |
| adapter.ts | `packages/next/src/server/web/adapter.ts` | ソース | Middleware実行時のNextResponse利用箇所 |
