# 通知設計書 7-HTTPサーバーリクエスト通知

## 概要

本ドキュメントは、Node.jsのHTTPサーバーモジュールにおける診断チャンネル通知機能の設計書である。

### 本通知の処理概要

HTTPサーバーリクエスト通知は、Node.jsアプリケーションがHTTPサーバーとしてリクエストを受信・処理する際の各フェーズ（リクエスト開始・レスポンス作成・レスポンス完了）で診断チャンネルに通知を送信する機能を提供する。これにより、HTTPサーバーの動作を外部から監視・計装することが可能となる。

**業務上の目的・背景**：Webアプリケーションの運用において、リクエストのレイテンシ、エラー率、スループットなどのメトリクス収集は不可欠である。HTTPサーバー通知は、Express、Koa、Fastifyなどのフレームワークに依存せず、Node.jsのHTTPサーバーレベルでこれらの情報を収集する標準的な方法を提供する。APMツールとの連携により、リクエストのトレーシングやパフォーマンス分析が可能となる。

**通知の送信タイミング**：
- http.server.request.start: リクエストの処理開始時
- http.server.response.created: ServerResponseオブジェクト作成時
- http.server.response.finish: レスポンス送信完了時

**通知の受信者**：各診断チャンネルに対してsubscribe()で登録したコールバック関数。APMツール、トレーシングライブラリ、カスタム監視コードなどが想定される。

**通知内容の概要**：リクエストオブジェクト、レスポンスオブジェクト、ソケット、サーバーインスタンスなど、HTTPリクエスト処理の状態に関する情報。

**期待されるアクション**：購読者は受信したデータを使用して、リクエストのトレーシング、メトリクス収集、ログ出力、リクエストIDの付与などを行う。

## 通知種別

内部イベント通知（diagnostics_channel）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（パフォーマンスクリティカル） |
| リトライ | なし（同期実行のため） |

### 送信先決定ロジック

各チャンネルに対してsubscribe()を呼び出した購読者に送信される。hasSubscribersで事前チェックを行い、購読者がいない場合はpublish()をスキップしてパフォーマンスオーバーヘッドを最小化。

## 通知テンプレート

### チャンネル一覧

| チャンネル名 | タイミング | 説明 |
|-------------|---------|------|
| http.server.request.start | リクエスト処理開始時 | parserOnIncoming()内でリクエストオブジェクト作成後に発火 |
| http.server.response.created | レスポンス作成時 | ServerResponseコンストラクタ内で発火 |
| http.server.response.finish | レスポンス完了時 | resOnFinish()内でレスポンス送信完了後に発火 |

### データ構造

```javascript
// http.server.request.start
{
  request: IncomingMessage,  // HTTPリクエストオブジェクト
  response: ServerResponse,  // HTTPレスポンスオブジェクト
  socket: Socket,           // ソケットオブジェクト
  server: Server            // HTTPサーバーインスタンス
}

// http.server.response.created
{
  request: IncomingMessage,  // HTTPリクエストオブジェクト
  response: ServerResponse   // HTTPレスポンスオブジェクト
}

// http.server.response.finish
{
  request: IncomingMessage,  // HTTPリクエストオブジェクト
  response: ServerResponse,  // HTTPレスポンスオブジェクト
  socket: Socket,           // ソケットオブジェクト
  server: Server            // HTTPサーバーインスタンス
}
```

### 添付ファイル

該当なし（プログラム内部通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| request | HTTPリクエストオブジェクト | IncomingMessageインスタンス | Yes |
| response | HTTPレスポンスオブジェクト | ServerResponseインスタンス | Yes |
| socket | ソケットオブジェクト | Socketインスタンス | 一部 |
| server | HTTPサーバーインスタンス | Serverインスタンス | 一部 |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| レスポンス作成 | new ServerResponse() | hasSubscribers == true | ServerResponseコンストラクタ完了時 |
| リクエスト処理開始 | parserOnIncoming() | hasSubscribers == true | リクエストオブジェクト準備完了時 |
| レスポンス完了 | resOnFinish() | hasSubscribers == true | レスポンス送信完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 購読者なし | hasSubscribersがfalseの場合、publish()をスキップ |
| アップグレードリクエスト | WebSocketアップグレード等ではrequest.startが発火しない場合がある |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[クライアントからリクエスト受信] --> B[HTTPパーサーでリクエスト解析]
    B --> C[parserOnIncoming呼び出し]
    C --> D[ServerResponse作成]
    D --> E{hasSubscribers?}
    E -->|Yes| F[http.server.response.created発火]
    E -->|No| G[スキップ]
    F --> H{hasSubscribers?}
    G --> H
    H -->|Yes| I[http.server.request.start発火]
    H -->|No| J[スキップ]
    I --> K[requestイベント発火]
    J --> K
    K --> L[アプリケーション処理]
    L --> M[response.end呼び出し]
    M --> N[resOnFinish呼び出し]
    N --> O{hasSubscribers?}
    O -->|Yes| P[http.server.response.finish発火]
    O -->|No| Q[スキップ]
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | メモリ内オブジェクトのみ使用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | データベース更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| クライアント切断 | クライアントが接続を切断 | resOnFinishは呼び出されないことがある |
| タイムアウト | リクエストタイムアウト | タイムアウトイベントが発火、診断チャンネルへの通知は行われない |
| パースエラー | 不正なHTTPリクエスト | clientErrorイベントが発火 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（通知自体にはリトライなし） |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（制限なし） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（プログラム実行中は常時利用可能）

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

- リクエストオブジェクトには認証ヘッダー（Cookie、Authorization等）が含まれる可能性があるため、購読者はログ出力時に機密情報をマスクすべき
- リクエストボディに機密データ（パスワード、クレジットカード番号等）が含まれる場合があるため、適切な取り扱いが必要
- 購読者のパフォーマンスがHTTPサーバー全体のスループットに影響するため、軽量な処理を心がける

## 備考

- Node.js v18.11.0でhttp.server.request.startが追加
- Node.js v18.11.0でhttp.server.response.createdが追加
- Node.js v18.11.0でhttp.server.response.finishが追加
- hasSubscribersチェックにより、購読者がいない場合のオーバーヘッドは最小限
- パフォーマンス監視（PerformanceObserver）との併用も可能
- KeepAlive接続では複数のリクエストで同じソケットが再利用される

---

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

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

### 推奨読解順序

#### Step 1: チャンネル定義を理解する

まず、診断チャンネルの定義箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | _http_server.js | `lib/_http_server.js` | 103-106行目：3つの診断チャンネルの定義 |

**読解のコツ**: dc.channel()で作成されるチャンネル名のパターンを確認する。

#### Step 2: ServerResponse作成時の通知を理解する

ServerResponseのコンストラクタ内での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | _http_server.js | `lib/_http_server.js` | 202-240行目：ServerResponseコンストラクタ |

**主要処理フロー**:
1. **202行目**: ServerResponse関数の開始
2. **234-239行目**: response.created通知の発火

#### Step 3: リクエスト処理開始時の通知を理解する

parserOnIncoming内での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | _http_server.js | `lib/_http_server.js` | 1184-1315行目：parserOnIncoming関数 |

**主要処理フロー**:
- **1211-1215行目**: ServerResponseの作成
- **1224-1231行目**: request.start通知の発火

#### Step 4: レスポンス完了時の通知を理解する

resOnFinish内での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | _http_server.js | `lib/_http_server.js` | 1114-1167行目：resOnFinish関数 |

**主要処理フロー**:
- **1115-1122行目**: response.finish通知の発火

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

```
HTTP接続確立
    │
    └─ connectionListener() [697行目]
           │
           └─ parserOnIncoming() [1184行目]
                  │
                  ├─ new ServerResponse() [202行目]
                  │      │
                  │      └─ onResponseCreatedChannel.publish() [234-239行目]
                  │             └─ { request, response }
                  │
                  ├─ onRequestStartChannel.publish() [1224-1231行目]
                  │      └─ { request, response, socket, server }
                  │
                  └─ server.emit('request', req, res)

response.end() → response._finish()
    │
    └─ resOnFinish() [1114行目]
           │
           └─ onResponseFinishChannel.publish() [1115-1122行目]
                  └─ { request, response, socket, server }
```

### データフロー図

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

クライアントリクエスト    HTTPサーバー              診断チャンネル購読者
    │                        │                            │
    ▼                        ▼                            ▼
TCP接続 ──────────▶ connectionListener ──────▶ 接続処理
    │                        │                            │
    │                        ▼                            ▼
    │              new ServerResponse() ──────▶ response.created
    │                        │                            │
    │                        ▼                            ▼
    │              parserOnIncoming() ────────▶ request.start
    │                        │                            │
    │                        ▼                            ▼
    │              アプリケーション処理
    │                        │                            │
    │                        ▼                            ▼
    └─────────────▶ resOnFinish() ─────────────▶ response.finish
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| _http_server.js | `lib/_http_server.js` | ソース | HTTPサーバー実装、診断チャンネル通知 |
| diagnostics_channel.js | `lib/diagnostics_channel.js` | ソース | diagnostics_channelモジュール |
| _http_common.js | `lib/_http_common.js` | ソース | HTTP共通処理 |
| _http_incoming.js | `lib/_http_incoming.js` | ソース | IncomingMessageクラス |
| _http_outgoing.js | `lib/_http_outgoing.js` | ソース | OutgoingMessageクラス |
