# 機能設計書 23-Route Handlers

## 概要

本ドキュメントは、Next.js App RouterにおけるRoute Handlers機能の設計を記述する。Route Handlersは、`route.ts`（または`route.js`）ファイルによるAPIエンドポイントの定義機能であり、Web標準のRequest/Responseオブジェクトを使用してHTTPリクエストを処理する。

### 本機能の処理概要

**業務上の目的・背景**：Webアプリケーションでは、フロントエンドからのデータ取得・送信を処理するAPIエンドポイントが必要である。Route HandlersはApp Router内でWeb標準のAPIを使用してエンドポイントを定義する仕組みを提供し、Pages Routerの`pages/api/`ディレクトリに代わるモダンなAPI定義方法を実現する。

**機能の利用シーン**：RESTful APIの構築、Webhookの受信エンドポイント、フォーム送信の処理、外部APIとのプロキシ、ファイルアップロード処理、ストリーミングレスポンスの提供など。

**主要な処理内容**：
1. HTTPメソッド別のハンドラ関数解決（GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS）
2. Web標準のRequest/Responseによるリクエスト・レスポンス処理
3. 静的生成（Static Generation）対応とダイナミックレンダリング制御
4. Cookie、ヘッダー操作、リダイレクト処理
5. OpenTelemetryトレーシング統合

**関連システム・外部連携**：NextRequest/NextResponseによるCookieやヘッダーの拡張操作、キャッシュシステム（fetch拡張）、Server Actions、OpenTelemetryトレーシングと連携する。

**権限による制御**：ハンドラ関数内で独自の認証・認可ロジックを実装可能。フレームワークレベルでの組み込み権限制御はない。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | Route HandlersはAPIエンドポイントであり、直接的な画面はない。フロントエンドの各画面からAPI呼び出しの対象となる |

## 機能種別

API処理 / CRUD操作 / データ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| req | NextRequest | Yes | HTTPリクエストオブジェクト | Web標準Requestを拡張 |
| ctx.params | Promise<Record<string, string \| string[]>> | No | 動的ルートパラメータ | Dynamic Routeの場合のみ提供 |
| HTTP Method | string | Yes | リクエストのHTTPメソッド | GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONSのいずれか |

### 入力データソース

- HTTPリクエスト（クライアントからのfetch呼び出し、外部Webhook等）
- 動的ルートパラメータ（URLパスから抽出）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Response | Response | Web標準Responseオブジェクト |
| headers | Headers | レスポンスヘッダー（Cookie含む） |
| status | number | HTTPステータスコード |
| body | ReadableStream \| ArrayBuffer \| string \| null | レスポンスボディ |

### 出力先

- HTTPレスポンスとしてクライアントに送信

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ HTTPメソッドとパスに基づいてRoute Handlerにルーティング
2. ハンドラ解決
   └─ resolve()メソッドでHTTPメソッドに対応するハンドラ関数を取得
3. ストア初期化
   └─ WorkStore、RequestStore、ActionStoreを生成しAsyncLocalStorageにセット
4. dynamic設定の適用
   └─ force-dynamic/force-static/error/autoに基づくリクエストプロキシ設定
5. ハンドラ実行
   └─ do()メソッドでハンドラを実行（patchFetch適用、トレーシング統合）
6. レスポンス処理
   └─ Cookie統合、リダイレクト処理、レスポンスバリデーション
7. 再検証処理
   └─ pending revalidatesの実行
```

### フローチャート

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B["resolve(method)"]
    B --> C{有効なHTTPメソッド?}
    C -->|No| D["400 Bad Request"]
    C -->|Yes| E[WorkStore/RequestStore初期化]
    E --> F{dynamic設定}
    F -->|force-dynamic| G[forceDynamic=true]
    F -->|force-static| H[リクエストをProxyでラップ]
    F -->|error| I[dynamicShouldError=true]
    F -->|auto/undefined| J["proxyNextRequest()"]
    G --> K["do()ハンドラ実行"]
    H --> K
    I --> K
    J --> K
    K --> L{静的生成?}
    L -->|Yes| M[プリレンダー処理]
    L -->|No| N[通常実行]
    M --> O{レスポンスはResponse?}
    N --> O
    O -->|No| P["500 Internal Error"]
    O -->|Yes| Q[Cookie統合]
    Q --> R[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | 大文字メソッド必須 | HTTPメソッドハンドラは大文字でエクスポートする必要がある | 常時（小文字の場合は開発時に警告） |
| BR-23-02 | default export禁止 | デフォルトエクスポートは使用不可、名前付きエクスポートが必要 | 常時（使用時は開発時に警告） |
| BR-23-03 | Response返却必須 | ハンドラはResponseまたはNextResponseを返す必要がある | 常時（それ以外はエラー） |
| BR-23-04 | 静的メソッド | GETとHEADのみが静的生成の対象 | isStaticGeneration時 |
| BR-23-05 | NextResponse.rewrite()禁止 | Route Handler内でNextResponse.rewrite()は使用不可 | 常時 |
| BR-23-06 | NextResponse.next()禁止 | Route Handler内でNextResponse.next()は使用不可 | 常時 |
| BR-23-07 | リダイレクト時303 | Server Action内のリダイレクトは303（See Other）を使用 | isAction時 |

### 計算ロジック

非静的メソッドの判定：POST、PUT、DELETE、PATCH、OPTIONSのいずれかが定義されている場合、`hasNonStaticMethods`がtrueとなり、静的生成時にDynamicServerErrorをスローする。

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

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

該当なし。Route Handlers自体はデータベースに直接アクセスしない。ハンドラ関数内でユーザーが独自にデータベースアクセスを実装する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | Bad Request | 無効なHTTPメソッド | 有効なメソッド名を使用 |
| 500 | Internal Error | ハンドラがResponseを返さない | Response/NextResponseを返すようにする |
| - | DynamicServerError | 静的生成中に動的APIを使用 | dynamicオプションを適切に設定 |
| - | StaticGenBailoutError | dynamic="error"で動的データにアクセス | dynamic設定を見直す |

### リトライ仕様

フレームワークレベルでのリトライ機構はない。アプリケーション層で必要に応じて実装する。

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

該当なし。ハンドラ関数内でユーザーが独自にトランザクション管理を実装する。

## パフォーマンス要件

- Route HandlerはEdge RuntimeとNode.js Runtimeの両方で実行可能
- 静的生成対応により、GETリクエストのレスポンスをビルド時にキャッシュ可能
- OpenTelemetryトレーシングによるパフォーマンス計測が組み込まれている

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

- HTTPメソッドのバリデーションにより、不正なメソッド名によるRCE（Remote Code Execution）を防止
- `isHTTPMethod`による厳密なメソッド名チェック
- Server Actionのリダイレクトは303ステータスを使用し、POSTの再送信を防止

## 備考

- Route Handlersは`app/api/`以外のディレクトリにも配置可能（例：`app/dashboard/route.ts`）
- 同一ルートに`page.tsx`と`route.ts`を共存させることはできない
- GETハンドラのみの場合、デフォルトでHEADメソッドも自動的にサポートされる

---

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

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

### 推奨読解順序

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

Route Handlerモジュールの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | module.ts | `packages/next/src/server/route-modules/app-route/module.ts` | `AppRouteHandlerFn`、`AppRouteHandlers`、`AppRouteUserlandModule`の型定義（140-169行目） |

**読解のコツ**: `AppRouteHandlerFn`はWeb標準の`Request`を拡張した`NextRequest`を第1引数、動的パラメータを含むコンテキストを第2引数として受け取る。

#### Step 2: エントリーポイントを理解する

`handle`メソッドがRoute Handlerのエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | module.ts | `packages/next/src/server/route-modules/app-route/module.ts` | `handle()`メソッド（694-849行目）がメインエントリーポイント |

**主要処理フロー**:
1. **699行目**: `resolve()`でHTTPメソッドに対応するハンドラを取得
2. **702-707行目**: 静的生成コンテキストの構築
3. **712-715行目**: ActionStoreの初期化
4. **717-722行目**: implicit tagsの取得
5. **724-730行目**: RequestStoreの生成
6. **732行目**: WorkStoreの生成
7. **737-826行目**: AsyncLocalStorage.runでハンドラを実行
8. **760-797行目**: dynamic設定に基づくリクエストプロキシ設定

#### Step 3: ハンドラ実行ロジックを理解する

`do`メソッドが実際のハンドラ実行と結果処理を担当。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | module.ts | `packages/next/src/server/route-modules/app-route/module.ts` | `do()`メソッド（303-692行目）のハンドラ実行ロジック |

**主要処理フロー**:
- **319-322行目**: `patchFetch()`によるfetch APIの拡張
- **324-331行目**: ハンドラコンテキスト（params）の構築
- **354-604行目**: 静的生成時のプリレンダー処理（prospective render + final render）
- **613-648行目**: エラーハンドリング（リダイレクト、HTTPアクセスフォールバック）
- **650-666行目**: レスポンスバリデーション（Response型チェック）
- **682-689行目**: Cookie統合処理

#### Step 4: ヘルパー関数を理解する

自動メソッド実装とユーティリティ。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | auto-implement-methods.ts | `packages/next/src/server/route-modules/app-route/helpers/auto-implement-methods.ts` | HEADメソッドやOPTIONSの自動実装 |
| 4-2 | is-static-gen-enabled.ts | `packages/next/src/server/route-modules/app-route/helpers/is-static-gen-enabled.ts` | 静的生成の有効判定 |

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

```
AppRouteRouteModule.handle() [module.ts:694]
    |
    +-- resolve(method) [module.ts:295]
    |       +-- isHTTPMethod() バリデーション
    |
    +-- createWorkStore() / createRequestStoreForAPI()
    |
    +-- actionAsyncStorage.run()
    |       +-- workUnitAsyncStorage.run()
    |           +-- workAsyncStorage.run()
    |               +-- dynamic設定によるプロキシ適用
    |               +-- getTracer().trace()
    |                   +-- do() [module.ts:303]
    |                       +-- patchFetch()
    |                       +-- handler(request, handlerContext) ← ユーザー定義関数
    |                       +-- executeRevalidates()
    |                       +-- appendMutableCookies()
    |
    +-- レスポンスバリデーション
```

### データフロー図

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

NextRequest         ──>  resolve(method)               ──>  handler関数
                          |
HTTPメソッド         ──>  WorkStore/RequestStore初期化   ──>  AsyncLocalStorage
                          |
dynamic設定         ──>  リクエストプロキシ適用          ──>  Proxied Request
                          |
handler実行         ──>  patchFetch + ユーザーハンドラ   ──>  Response
                          |
Response            ──>  Cookie統合 + バリデーション     ──>  HTTPレスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| module.ts | `packages/next/src/server/route-modules/app-route/module.ts` | ソース | Route Handlerモジュールのメイン実装（1253行） |
| auto-implement-methods.ts | `packages/next/src/server/route-modules/app-route/helpers/auto-implement-methods.ts` | ソース | HEAD/OPTIONSメソッドの自動実装 |
| is-static-gen-enabled.ts | `packages/next/src/server/route-modules/app-route/helpers/is-static-gen-enabled.ts` | ソース | 静的生成有効判定 |
| parsed-url-query-to-params.ts | `packages/next/src/server/route-modules/app-route/helpers/parsed-url-query-to-params.ts` | ソース | クエリパラメータからparamsへの変換 |
| clean-url.ts | `packages/next/src/server/route-modules/app-route/helpers/clean-url.ts` | ソース | URLクリーニング |
| shared-modules.ts | `packages/next/src/server/route-modules/app-route/shared-modules.ts` | ソース | 共有モジュール |
| patch-fetch.ts | `packages/next/src/server/lib/patch-fetch.ts` | ソース | fetch API拡張 |
| request.ts | `packages/next/src/server/web/spec-extension/request.ts` | ソース | NextRequestの実装 |
| http.ts | `packages/next/src/server/web/http.ts` | ソース | HTTPメソッド定義とバリデーション |
| app-route-route-definition.ts | `packages/next/src/server/route-definitions/app-route-route-definition.ts` | ソース | Route Handler用ルート定義型 |
