# 機能設計書 78-userAgent()

## 概要

本ドキュメントは、Next.jsの`userAgent()`関数の設計について記述する。`userAgent()`はHTTPリクエストのUser-Agentヘッダーを解析し、ブラウザ・デバイス・OS・エンジン・CPU情報およびボット判定結果を提供するユーティリティ関数である。

### 本機能の処理概要

`userAgent()`関数は、リクエストオブジェクトのUser-Agentヘッダー文字列を`ua-parser-js`ライブラリで解析し、構造化されたUserAgentオブジェクトを返す。Middlewareやサーバーサイドコードでユーザーエージェント情報に基づく条件分岐を行うために使用される。

**業務上の目的・背景**：User-Agent文字列は構造が複雑であり、手動でのパースはエラーの原因になりやすい。また、ボット検出（クローラー、ソーシャルメディアボット等）は多くのWebアプリケーションで必要となる。`userAgent()`はこれらを一貫したAPIで提供し、開発者がデバイスやブラウザに応じた最適な処理を実装できるようにする。

**機能の利用シーン**：Middlewareでのボット検出とアクセス制御、モバイル/デスクトップ判定によるリダイレクト、ブラウザ互換性チェック、クローラーへの最適化対応、分析データへのデバイス情報付与。

**主要な処理内容**：
1. リクエストヘッダーから`user-agent`文字列を取得
2. `ua-parser-js`による文字列パース（browser, device, engine, os, cpu情報の抽出）
3. `isBot()`関数による主要ボット検出（正規表現マッチング）
4. 構造化されたUserAgentオブジェクトの返却

**関連システム・外部連携**：ua-parser-js（コンパイル済み依存ライブラリ）

**権限による制御**：特になし。userAgent()は純粋な解析関数であり、任意のコンテキストで使用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | userAgent()は画面に直接関連しない。サーバーサイドでのUser-Agent解析に使用される |

## 機能種別

データ解析 / ユーティリティ

## 入力仕様

### 入力パラメータ

#### userAgent()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| { headers } | { headers: Headers } | Yes | headersプロパティを持つオブジェクト（NextRequest等） | - |

#### userAgentFromString()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string \| undefined | Yes | User-Agent文字列 | undefinedの場合isBot=falseとなる |

#### isBot()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string | Yes | User-Agent文字列 | - |

### 入力データソース

HTTPリクエストのUser-Agentヘッダー。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isBot | boolean | ボットかどうかの判定結果 |
| ua | string | 元のUser-Agent文字列 |
| browser | { name?: string, version?: string, major?: string } | ブラウザ情報 |
| device | { model?: string, type?: string, vendor?: string } | デバイス情報 |
| engine | { name?: string, version?: string } | レンダリングエンジン情報 |
| os | { name?: string, version?: string } | OS情報 |
| cpu | { architecture?: string } | CPU情報 |

### 出力先

呼び出し元のサーバーサイドコード内で使用される。

## 処理フロー

### 処理シーケンス

```
1. userAgent({ headers }) 呼び出し
   └─ headers.get('user-agent')でUser-Agent文字列を取得
2. userAgentFromString(input) 呼び出し
   └─ parseua(input) でua-parser-jsによるパース
   └─ isBot(input) でボット判定
3. 結果オブジェクトの構築
   └─ ua-parser-jsの結果にisBotフラグを追加
4. UserAgentオブジェクトの返却
```

### フローチャート

```mermaid
flowchart TD
    A[userAgent headers] --> B[headers.get user-agent]
    B --> C[userAgentFromString]
    C --> D[parseua ua-parser-js]
    C --> E[isBot 正規表現マッチ]
    D --> F[UserAgentオブジェクト構築]
    E --> F
    F --> G[返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-78-01 | ボット検出対象 | Googlebot, Bingbot, DuckDuckBot, baiduspider, yandex, sogou等の主要検索エンジンボット、およびLinkedInBot, Twitterbot, facebookexternalhit, Discordbot, WhatsApp, GPTBot等のソーシャル/AIボットを検出 | isBot()呼び出し時 |
| BR-78-02 | undefinedの扱い | User-Agent文字列がundefinedの場合、isBot=falseとなる | userAgentFromString(undefined) |
| BR-78-03 | 大文字小文字無視 | ボット検出の正規表現はケースインセンシティブ（/i フラグ） | isBot()呼び出し時 |

### 計算ロジック

ボット検出は以下の正規表現パターンによるマッチングで行われる：

```
/Googlebot|Mediapartners-Google|AdsBot-Google|googleweblight|Storebot-Google|
Google-PageRenderer|Google-InspectionTool|Bingbot|BingPreview|Slurp|DuckDuckBot|
baiduspider|yandex|sogou|LinkedInBot|bitlybot|tumblr|vkShare|quora link preview|
facebookexternalhit|facebookcatalog|Twitterbot|applebot|redditbot|Slackbot|
Discordbot|WhatsApp|SkypeUriPreview|ia_archiver|GPTBot/i
```

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

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

userAgent()はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | - | userAgent()はエラーをスローしない | - |

### リトライ仕様

該当なし。

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

該当なし。

## パフォーマンス要件

- ua-parser-jsによるパースは同期的に実行される
- 正規表現によるボット検出は軽量な文字列マッチングのみ

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

- User-Agent文字列はクライアントが自由に設定可能であり、偽装される可能性がある
- ボット検出はヒューリスティックであり、未知のボットや偽装ボットを完全には検出できない

## 備考

- `userAgent()`はNextRequestの旧`ua`プロパティの代替として提供された
- `next/server`からインポートして使用する
- `isBot()`と`userAgentFromString()`も個別にエクスポートされている

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user-agent.ts | `packages/next/src/server/web/spec-extension/user-agent.ts` | UserAgentインターフェース（3-27行目）の構造を確認。browser, device, engine, os, cpuの各プロパティはOptionalのname/versionを持つ |

**読解のコツ**: UserAgentインターフェースはua-parser-jsの出力にisBotプロパティを追加したもの。各フィールドはOptionalであり、User-Agent文字列から情報が抽出できなかった場合はundefinedになる。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | user-agent.ts | `packages/next/src/server/web/spec-extension/user-agent.ts` | 3つのエクスポート関数（isBot: 29-33, userAgentFromString: 35-40, userAgent: 42-44）を確認。全体で45行のコンパクトなファイル |

**主要処理フロー**:
1. **29-33行目**: `isBot(input)` - 正規表現によるボット判定。主要なクローラーとソーシャルボットをカバー
2. **35-40行目**: `userAgentFromString(input)` - parseua()で解析した結果にisBot判定を追加
3. **42-44行目**: `userAgent({ headers })` - headersからUser-Agent文字列を取得してuserAgentFromStringに委譲

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

```
userAgent({ headers }) [user-agent.ts:42]
    |
    +-- headers.get('user-agent')
    +-- userAgentFromString(ua) [user-agent.ts:35]
            |
            +-- parseua(input) [ua-parser-js]
            +-- isBot(input) [user-agent.ts:29]
                    +-- RegExp.test(input) [正規表現マッチング]
```

### データフロー図

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

{ headers: Headers } --> userAgent()                UserAgent
                            |                          |
                            +-> headers.get()          +-- isBot: boolean
                            |   'user-agent'           +-- ua: string
                            |                          +-- browser: {...}
                            +-> parseua() ------->     +-- device: {...}
                            |   (ua-parser-js)         +-- engine: {...}
                            |                          +-- os: {...}
                            +-> isBot() -------->      +-- cpu: {...}
                                (正規表現)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| user-agent.ts | `packages/next/src/server/web/spec-extension/user-agent.ts` | ソース | userAgent()関数本体（45行） |
| ua-parser-js | `packages/next/src/compiled/ua-parser-js/` | コンパイル済み | User-Agent文字列パーサー |
