# 機能設計書 36-Microsoft.Extensions.Http

## 概要

本ドキュメントは、Microsoft.Extensions.Http（HttpClientファクトリ）機能の設計内容を記述する。この機能はHttpClientインスタンスの作成・管理を抽象化し、接続プーリング、名前付きクライアント、型付きクライアントなどの高度な機能を提供する。

### 本機能の処理概要

Microsoft.Extensions.Httpは、IHttpClientFactoryインターフェースを通じてHttpClientの作成と管理を一元化するフレームワークである。HttpClientの再利用、ハンドラーのライフタイム管理、ロギング統合を提供する。

**業務上の目的・背景**：HttpClientの直接インスタンス化は、ソケット枯渇やDNS変更への未対応などの問題を引き起こす。このライブラリは、HttpMessageHandlerの適切なライフタイム管理を行い、これらの問題を解決する。名前付きクライアントや型付きクライアントにより、APIクライアントの設定を集中管理できる。

**機能の利用シーン**：外部API呼び出し、マイクロサービス間通信、Webスクレイピング、RESTful APIクライアントの実装など、HTTP通信が必要なあらゆるシナリオで使用される。Pollyとの統合により、リトライやサーキットブレーカーも容易に実装できる。

**主要な処理内容**：
1. IHttpClientFactoryを通じたHttpClient生成
2. HttpMessageHandlerのライフタイム管理（デフォルト2分）
3. 名前付きクライアントによる設定の集中管理
4. 型付きクライアントによるDI統合
5. DelegatingHandlerチェーンの構築
6. ハンドラーの自動クリーンアップ

**関連システム・外部連携**：Microsoft.Extensions.DependencyInjection、Microsoft.Extensions.Logging、Microsoft.Extensions.Options、Polly等の回復性ライブラリと連携する。

**権限による制御**：HttpClient自体に権限制御はないが、ハンドラーで認証ヘッダーの付与等が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

データ連携 / HTTP通信 / ファクトリパターン

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | クライアント名 | null不可 |
| baseAddress | Uri | No | ベースアドレス | 有効なURI |
| handlerLifetime | TimeSpan | No | ハンドラー有効期間 | 正の値、デフォルト2分 |
| configureClient | Action<HttpClient> | No | クライアント設定デリゲート | - |
| configureHandler | Action<HttpMessageHandlerBuilder> | No | ハンドラー設定デリゲート | - |

### 入力データソース

- プログラマティックな設定（AddHttpClient）
- IConfiguration経由の設定
- 型付きクライアントの型パラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| HttpClient | HttpClient | 生成されたHttpClientインスタンス |
| HttpMessageHandler | HttpMessageHandler | 生成されたハンドラー |

### 出力先

- アプリケーションのHTTP通信
- 外部API/サービスへのリクエスト

## 処理フロー

### 処理シーケンス

```
1. 登録フェーズ
   └─ AddHttpClient()でサービスとオプションを登録
2. ファクトリ作成フェーズ
   └─ DefaultHttpClientFactoryがDIから解決される
3. クライアント作成フェーズ
   └─ CreateClient()でHttpClientを生成
4. ハンドラー取得/作成フェーズ
   └─ ActiveHandlerTrackingEntryをキャッシュから取得または新規作成
5. タイマー開始フェーズ
   └─ ハンドラー有効期限タイマーを開始
6. クライアント構成フェーズ
   └─ HttpClientActionsを適用
7. 期限切れフェーズ
   └─ タイマー満了でExpiredHandlersキューに移動
8. クリーンアップフェーズ
   └─ GC可能になったハンドラーをDispose
```

### フローチャート

```mermaid
flowchart TD
    A[AddHttpClient登録] --> B[IHttpClientFactory解決]
    B --> C[CreateClient呼び出し]
    C --> D[CreateHandler呼び出し]
    D --> E{キャッシュにハンドラーあり?}
    E -->|Yes| F[既存ハンドラー取得]
    E -->|No| G[CreateHandlerEntry]
    G --> H[HttpMessageHandlerBuilder取得]
    H --> I[フィルターチェーン適用]
    I --> J[ハンドラー構築]
    J --> K[LifetimeTrackingHttpMessageHandler作成]
    K --> L[ActiveHandlerTrackingEntry作成]
    L --> F
    F --> M[タイマー開始]
    M --> N[new HttpClient with handler]
    N --> O[HttpClientActions適用]
    O --> P[HttpClient返却]
    M --> Q{タイマー満了?}
    Q -->|Yes| R[ExpiredHandlersキューに移動]
    R --> S[クリーンアップタイマー開始]
    S --> T{CanDispose?}
    T -->|Yes| U[ハンドラーDispose]
    T -->|No| V[キューに戻す]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-36-01 | ハンドラー再利用 | 同名クライアントは有効期間内のハンドラーを共有 | CreateClient時 |
| BR-36-02 | 遅延破棄 | ハンドラーはGC可能になるまで破棄されない | 期限切れ後 |
| BR-36-03 | スコープ作成 | SuppressHandlerScope=falseの場合、ハンドラービルダー用スコープを作成 | ハンドラー作成時 |
| BR-36-04 | フィルターチェーン | フィルターは逆順に適用され、実行は登録順 | ハンドラー構築時 |

### 計算ロジック

ハンドラー有効期限管理：
1. 最初のCreateClient呼び出し時にタイマー開始
2. HandlerLifetime経過後、ActiveHandlersから削除
3. ExpiredHandlersキューに追加
4. 10秒間隔のクリーンアップでGC可能ハンドラーをDispose

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ArgumentNullException | nameがnull | 有効な名前を指定 |
| - | HttpRequestException | HTTP通信エラー | リトライまたはエラーハンドリング |

### リトライ仕様

HttpClientFactory自体はリトライ機能を持たない。Pollyとの統合でリトライ実装が可能。

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

該当なし

## パフォーマンス要件

- ハンドラー取得: ConcurrentDictionaryベースでO(1)
- クリーンアップ: 10秒間隔でバックグラウンド実行
- デフォルトハンドラー有効期間: 2分

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

- SSL/TLS設定の適切な構成
- 認証ヘッダーの安全な管理
- 機密情報のログ出力回避

## 備考

- HttpClientのDisposeは不要（ハンドラーは共有されるため）
- プライマリハンドラーとしてSocketsHttpHandlerが推奨
- .NET 6以降、SocketsHttpHandlerのPooledConnectionLifetimeによるDNS対応も可能

---

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

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

### 推奨読解順序

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

HttpClientFactory の基本的なインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | IHttpClientFactory.cs | `src/libraries/Microsoft.Extensions.Http/src/IHttpClientFactory.cs` | ファクトリインターフェース |
| 1-2 | IHttpMessageHandlerFactory.cs | `src/libraries/Microsoft.Extensions.Http/src/IHttpMessageHandlerFactory.cs` | ハンドラーファクトリインターフェース |
| 1-3 | HttpClientFactoryOptions.cs | `src/libraries/Microsoft.Extensions.Http/src/HttpClientFactoryOptions.cs` | オプション設定 |

**読解のコツ**: IHttpClientFactory→IHttpMessageHandlerFactory→HttpClientFactoryOptionsの関係を理解する。ファクトリはハンドラーを管理し、オプションで動作を設定する。

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

DefaultHttpClientFactoryの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DefaultHttpClientFactory.cs | `src/libraries/Microsoft.Extensions.Http/src/DefaultHttpClientFactory.cs` | ファクトリの実装 |

**主要処理フロー**:
1. **62-101行目**: コンストラクタでサービス、オプション、フィルターを受け取り初期化
2. **103-117行目**: CreateClient()でハンドラーを取得し、HttpClientを作成、アクションを適用
3. **119-128行目**: CreateHandler()でキャッシュからハンドラーを取得またはCreateHandlerEntry()を呼び出し
4. **131-190行目**: CreateHandlerEntry()でハンドラーを構築（フィルターチェーン、LifetimeTrackingHandler）
5. **193-215行目**: ExpiryTimer_Tick()で期限切れハンドラーをExpiredHandlersキューに移動
6. **243-314行目**: CleanupTimer_Tick()でGC可能なハンドラーをDispose

#### Step 3: ハンドラートラッキングを理解する

ハンドラーのライフサイクル管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ActiveHandlerTrackingEntry.cs | `src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs` | アクティブハンドラーのトラッキング |
| 3-2 | ExpiredHandlerTrackingEntry.cs | `src/libraries/Microsoft.Extensions.Http/src/ExpiredHandlerTrackingEntry.cs` | 期限切れハンドラーのトラッキング |
| 3-3 | LifetimeTrackingHttpMessageHandler.cs | `src/libraries/Microsoft.Extensions.Http/src/LifetimeTrackingHttpMessageHandler.cs` | ライフタイム追跡用ラッパー |

**主要処理フロー**:
- **ActiveHandlerTrackingEntry**: 有効期限タイマーを持つアクティブなハンドラーエントリ
- **ExpiredHandlerTrackingEntry**: WeakReferenceでハンドラーを保持し、CanDisposeでGC可能性を判定
- **LifetimeTrackingHttpMessageHandler**: InnerHandlerの参照を保持し、ファクトリがライフタイムを制御

#### Step 4: 登録と拡張を理解する

DIへの登録方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | HttpClientBuilderExtensions.cs | `src/libraries/Microsoft.Extensions.Http/src/HttpClientBuilderExtensions.cs` | ビルダー拡張メソッド |
| 4-2 | HttpClientFactoryServiceCollectionExtensions.cs | `src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientFactoryServiceCollectionExtensions.cs` | サービス登録拡張 |

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

```
IHttpClientFactory.CreateClient(name)
    │
    ├─ CreateHandler(name)
    │      │
    │      └─ _activeHandlers.GetOrAdd(name, _entryFactory)
    │             │
    │             └─ CreateHandlerEntry(name)
    │                    │
    │                    ├─ _scopeFactory.CreateScope() (オプション)
    │                    │
    │                    ├─ HttpMessageHandlerBuilder取得
    │                    │
    │                    ├─ _filters配列を逆順にチェーン
    │                    │
    │                    ├─ builder.Build()
    │                    │
    │                    └─ new ActiveHandlerTrackingEntry()
    │
    ├─ StartHandlerEntryTimer(entry)
    │
    └─ new HttpClient(handler, disposeHandler: false)
           │
           └─ HttpClientActions適用

ExpiryTimer_Tick(state)
    │
    ├─ _activeHandlers.TryRemove(name)
    │
    └─ _expiredHandlers.Enqueue(new ExpiredHandlerTrackingEntry())
           │
           └─ StartCleanupTimer()

CleanupTimer_Tick()
    │
    └─ foreach (entry in _expiredHandlers)
           │
           ├─ entry.CanDispose? → Dispose()
           │
           └─ !CanDispose → Enqueue(entry)
```

### データフロー図

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

AddHttpClient() ───▶ IServiceCollection ───▶ HttpClientFactoryOptions
                                                    │
                                                    ▼
CreateClient() ───▶ DefaultHttpClientFactory ───▶ CreateHandler()
                                                    │
                                                    ▼
                                    _activeHandlers.GetOrAdd()
                                                    │
                                                    ▼
                                    HttpMessageHandlerBuilder
                                                    │
                                                    ▼
                                    フィルターチェーン適用
                                                    │
                                                    ▼
                              LifetimeTrackingHttpMessageHandler
                                                    │
                                                    ▼
                              new HttpClient(handler)
                                                    │
                                                    ▼
                              HttpClientActions適用
                                                    │
                                                    ▼
                                    HttpClient返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DefaultHttpClientFactory.cs | `src/libraries/Microsoft.Extensions.Http/src/DefaultHttpClientFactory.cs` | ソース | ファクトリ実装 |
| HttpClientFactoryOptions.cs | `src/libraries/Microsoft.Extensions.Http/src/HttpClientFactoryOptions.cs` | ソース | オプション |
| ActiveHandlerTrackingEntry.cs | `src/libraries/Microsoft.Extensions.Http/src/ActiveHandlerTrackingEntry.cs` | ソース | アクティブハンドラー |
| ExpiredHandlerTrackingEntry.cs | `src/libraries/Microsoft.Extensions.Http/src/ExpiredHandlerTrackingEntry.cs` | ソース | 期限切れハンドラー |
| LifetimeTrackingHttpMessageHandler.cs | `src/libraries/Microsoft.Extensions.Http/src/LifetimeTrackingHttpMessageHandler.cs` | ソース | ライフタイム追跡 |
| HttpMessageHandlerBuilder.cs | `src/libraries/Microsoft.Extensions.Http/src/HttpMessageHandlerBuilder.cs` | ソース | ハンドラービルダー |
| DefaultHttpMessageHandlerBuilder.cs | `src/libraries/Microsoft.Extensions.Http/src/DefaultHttpMessageHandlerBuilder.cs` | ソース | デフォルトビルダー |
| HttpClientBuilderExtensions.cs | `src/libraries/Microsoft.Extensions.Http/src/HttpClientBuilderExtensions.cs` | ソース | 拡張メソッド |
| LoggingHttpMessageHandler.cs | `src/libraries/Microsoft.Extensions.Http/src/Logging/LoggingHttpMessageHandler.cs` | ソース | ロギングハンドラー |
