# 機能設計書 18-リダイレクター

## 概要

本ドキュメントは、Laravel Frameworkのリダイレクター（Redirector）機能の設計を詳細に記述したものである。様々な種類のHTTPリダイレクトレスポンスを生成し、セッション連携による意図したURL管理機能を提供する。

### 本機能の処理概要

リダイレクターは、アプリケーション内でのページ遷移やフォーム送信後のリダイレクト処理を担当し、セッションを通じたフラッシュデータや意図したURLの管理を統合的に提供する。

**業務上の目的・背景**：Webアプリケーションでは、フォーム送信後のPOST-REDIRECT-GETパターン、認証後のリダイレクト、エラー発生時の戻り先指定など、様々なシーンでリダイレクトが必要となる。リダイレクターは、これらの処理を一貫したAPIで提供し、セッション連携によるintended URL（認証前にアクセスしようとしたURL）管理を実現する。

**機能の利用シーン**：
- フォーム送信後のリダイレクト（PRGパターン）
- 認証後の元のページへのリダイレクト
- バリデーションエラー時の入力画面への戻り
- 外部サイトへのリダイレクト
- 名前付きルートへのリダイレクト
- コントローラアクションへのリダイレクト

**主要な処理内容**：
1. 前のページへのリダイレクト（back メソッド）
2. 指定パスへのリダイレクト（to メソッド）
3. 名前付きルートへのリダイレクト（route メソッド）
4. コントローラアクションへのリダイレクト（action メソッド）
5. 外部URLへのリダイレクト（away メソッド）
6. 意図したURLへのリダイレクト（intended, guest メソッド）
7. 署名付きルートへのリダイレクト（signedRoute, temporarySignedRoute メソッド）

**関連システム・外部連携**：
- UrlGenerator：URL生成の委譲
- セッション：フラッシュデータと意図したURLの管理
- HTTPリクエスト：リダイレクトレスポンスの生成

**権限による制御**：リダイレクター自体は権限制御を持たない。認証ミドルウェアとの連携でゲストリダイレクトを実現。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | ログイン | 主画面 | 認証後リダイレクト（intended） |
| 3 | ダッシュボード | 関連画面 | 認証後デフォルトリダイレクト先 |

## 機能種別

リダイレクト / セッション連携 / HTTP処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| path | string | Yes（to時） | リダイレクト先パス | - |
| status | int | No | HTTPステータスコード | デフォルト302 |
| headers | array | No | 追加ヘッダー | - |
| secure | bool/null | No | HTTPS強制 | - |
| route | BackedEnum/string | Yes（route時） | ルート名 | 登録済みルート |
| parameters | mixed | No | ルートパラメータ | - |
| action | string/array | Yes（action時） | コントローラアクション | - |
| fallback | mixed | No（back時） | フォールバックURL | - |
| default | mixed | No（intended時） | デフォルトURL | デフォルト'/' |
| expiration | DateTimeInterface/DateInterval/int/null | No（signedRoute時） | 有効期限 | - |

### 入力データソース

- コントローラ：redirect()ヘルパー経由の呼び出し
- セッション：意図したURLの取得

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| response | RedirectResponse | リダイレクトレスポンス |

### 出力先

- HTTPレスポンス：302/301等のリダイレクトレスポンス

## 処理フロー

### 処理シーケンス

```
1. リダイレクト要求
   └─ back(), to(), route(), action(), away() 等の呼び出し
2. URL生成
   └─ UrlGenerator経由でURL生成
3. RedirectResponse生成
   └─ createRedirect でレスポンス作成
4. セッション設定
   └─ セッションがあればレスポンスに設定
5. リクエスト設定
   └─ 現在のリクエストをレスポンスに設定
6. レスポンス返却
   └─ RedirectResponseを返却
```

### フローチャート

```mermaid
flowchart TD
    A[リダイレクト要求] --> B{メソッド種別}
    B -->|back| C[前のURL取得]
    B -->|to| D[パスからURL生成]
    B -->|route| E[ルート名からURL生成]
    B -->|action| F[アクションからURL生成]
    B -->|away| G[外部URL使用]
    C --> H[createRedirect]
    D --> H
    E --> H
    F --> H
    G --> H
    H --> I[RedirectResponse生成]
    I --> J{セッションあり?}
    J -->|Yes| K[セッション設定]
    J -->|No| L[リクエスト設定]
    K --> L
    L --> M[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-18-01 | デフォルトステータス | リダイレクトのデフォルトステータスは302 | 全リダイレクト |
| BR-18-02 | backのフォールバック | refererがない場合はセッションのpreviousUrl、それもなければフォールバックまたは'/' | back()呼び出し時 |
| BR-18-03 | guestのintended保存 | GETリクエストかつルートありかつJSONでない場合のみ保存 | guest()呼び出し時 |
| BR-18-04 | intendedのpull | intendedはセッションから取得後削除 | intended()呼び出し時 |
| BR-18-05 | awayのバリデーション無効 | awayは外部URLをそのまま使用（バリデーションなし） | away()呼び出し時 |

### 計算ロジック

```php
// backのURL決定
url = $referrer ?? $session->previousUrl() ?? $fallback ?? '/'

// guestのintended決定
intended = $request->isMethod('GET') && $request->route() && !$request->expectsJson()
    ? $generator->full()
    : $generator->previous()
```

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

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

リダイレクターはデータベースを操作しない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | Redirector自体はDB操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RouteNotFoundException | route()で未定義のルート名 | ルート定義を確認 |
| - | InvalidArgumentException | action()で未定義のアクション | アクション定義を確認 |

### リトライ仕様

リダイレクト処理にリトライ機構はない。

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

リダイレクターはトランザクションを使用しない。

## パフォーマンス要件

- UrlGeneratorへの直接委譲で最小限のオーバーヘッド
- セッション操作は必要な場合のみ実行

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

- away()は外部URLをそのまま使用するため、ユーザー入力を直接渡さない
- open redirect攻撃への対策として、to()はアプリ内URLに限定
- signedRoute()による署名付きリダイレクトで改ざん検知

## 備考

- Macroableトレイト：カスタムリダイレクトメソッドの追加が可能
- RedirectResponse：Symfonyのレスポンスを拡張し、withメソッド等を提供

---

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

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

### 推奨読解順序

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

まず、リダイレクターが保持するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | プロパティ定義（$generator, $session）を確認 |

**読解のコツ**: Redirectorは2つの主要プロパティを持つ。`$generator`はUrlGeneratorへの参照、`$session`はセッションストアへの参照である。URL生成はすべてUrlGeneratorに委譲される。

#### Step 2: 基本リダイレクトを理解する

to、backメソッドによる基本的なリダイレクトを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | backメソッド（45-48行目） |
| 2-2 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | toメソッド（111-114行目） |
| 2-3 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | awayメソッド（124-127行目） |

**主要処理フロー**:
1. **45-48行目**: `back` - generator->previous()でURL取得、createRedirect呼び出し
2. **111-114行目**: `to` - generator->to()でURL生成、createRedirect呼び出し
3. **124-127行目**: `away` - 外部URLをそのままcreateRedirectに渡す

#### Step 3: ルートベースリダイレクトを理解する

route、actionメソッドによるルートベースのリダイレクトを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | routeメソッド（151-154行目） |
| 3-2 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | signedRouteメソッド（166-169行目） |
| 3-3 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | actionメソッド（195-198行目） |

**主要処理フロー**:
- **151-154行目**: `route` - generator->route()でURL生成
- **166-169行目**: `signedRoute` - generator->signedRoute()で署名付きURL生成
- **195-198行目**: `action` - generator->action()でURL生成

#### Step 4: 意図したURL管理を理解する

guest、intendedメソッドによる認証フローのサポートを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | guestメソッド（71-84行目） |
| 4-2 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | intendedメソッド（95-100行目） |
| 4-3 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | setIntendedUrlメソッド（256-261行目） |

**主要処理フロー**:
- **71-84行目**: `guest` - GET+ルートあり+非JSONなら現在URLを、それ以外は前のURLをintendedに保存
- **95-100行目**: `intended` - セッションからurl.intendedをpullしてリダイレクト
- **256-261行目**: `setIntendedUrl` - セッションにurl.intendedを保存

#### Step 5: レスポンス生成を理解する

createRedirectメソッドによるレスポンス生成を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Redirector.php | `src/Illuminate/Routing/Redirector.php` | createRedirectメソッド（208-217行目） |

**主要処理フロー**:
- **208-217行目**: `createRedirect` - RedirectResponse生成、セッションとリクエストを設定

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

```
Redirector::back($status, $headers, $fallback)
    │
    └─ UrlGenerator::previous($fallback)
           │
           ├─ $request->headers->get('referer')
           │
           └─ $session->previousUrl()
    │
    └─ Redirector::createRedirect($path, $status, $headers)
           │
           └─ new RedirectResponse($path, $status, $headers)
                  │
                  ├─ RedirectResponse::setSession($session)
                  │
                  └─ RedirectResponse::setRequest($request)

Redirector::guest($path, $status, $headers, $secure)
    │
    ├─ UrlGenerator::getRequest()
    │
    ├─ UrlGenerator::full() / previous()
    │
    ├─ Redirector::setIntendedUrl($intended)
    │      └─ $session->put('url.intended', $url)
    │
    └─ Redirector::to($path, $status, $headers, $secure)
           └─ UrlGenerator::to($path, [], $secure)

Redirector::intended($default, $status, $headers, $secure)
    │
    ├─ $session->pull('url.intended', $default)
    │
    └─ Redirector::to($path, $status, $headers, $secure)
```

### データフロー図

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

パス/ルート名      ───▶  UrlGenerator              ───▶  URL文字列
    │                        │
ステータス         ───▶  createRedirect()          ───▶  RedirectResponse
    │                        │
セッション         ───▶  setSession()              ───▶  セッション付きResponse
    │                        │
リクエスト         ───▶  setRequest()              ───▶  リクエスト付きResponse

GETリクエスト      ───▶  guest()                   ───▶  url.intended保存
    │                        │
url.intended       ───▶  intended()                ───▶  元のURLへリダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Redirector.php | `src/Illuminate/Routing/Redirector.php` | ソース | リダイレクターコア実装 |
| RedirectResponse.php | `src/Illuminate/Http/RedirectResponse.php` | ソース | リダイレクトレスポンス |
| UrlGenerator.php | `src/Illuminate/Routing/UrlGenerator.php` | ソース | URL生成（委譲先） |
| Store.php | `src/Illuminate/Session/Store.php` | ソース | セッションストア |
| RoutingServiceProvider.php | `src/Illuminate/Routing/RoutingServiceProvider.php` | ソース | サービスプロバイダー |
