# 機能設計書: System.Net.Http（HTTP通信）

## 1. 機能概要

### 1.1 機能名
System.Net.Http（HTTP通信）

### 1.2 機能ID
FUNC-013

### 1.3 機能説明
.NET ランタイムにおけるHTTP通信機能を提供するライブラリ。HTTP/1.1、HTTP/2、HTTP/3プロトコルに対応し、RESTful APIとの通信、ファイルダウンロード、Webリソースへのアクセスなど、現代的なHTTPクライアント機能を包括的に提供する。HttpClientクラスを中心とした非同期APIにより、効率的なネットワーク通信を実現する。

### 1.4 関連画面
- なし（基盤ライブラリのため直接的な関連画面は存在しない）

## 2. 機能要件

### 2.1 入力仕様

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| requestUri | string/Uri | Yes | リクエスト先URL |
| method | HttpMethod | No | HTTPメソッド（GET, POST等） |
| content | HttpContent | No | リクエストボディ |
| headers | HttpRequestHeaders | No | リクエストヘッダー |
| timeout | TimeSpan | No | タイムアウト時間 |
| cancellationToken | CancellationToken | No | キャンセルトークン |

### 2.2 出力仕様

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| HttpResponseMessage | HttpResponseMessage | HTTPレスポンス全体 |
| StatusCode | HttpStatusCode | ステータスコード |
| Headers | HttpResponseHeaders | レスポンスヘッダー |
| Content | HttpContent | レスポンスボディ |
| string | string | レスポンス文字列（GetStringAsync） |
| byte[] | byte[] | レスポンスバイト配列（GetByteArrayAsync） |
| Stream | Stream | レスポンスストリーム（GetStreamAsync） |

### 2.3 処理フロー

```
HttpClient.SendAsync(request)
    │
    ▼
┌─────────────────────┐
│ HttpRequestMessage   │
│ 構築・検証           │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ HttpMessageHandler   │
│ パイプライン         │
│ (DelegatingHandler)  │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ HttpClientHandler/   │
│ SocketsHttpHandler   │
│ (実際の送信)         │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ HTTP/1.1, 2, 3      │
│ プロトコル処理       │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│ HttpResponseMessage  │
│ 構築・返却           │
└─────────────────────┘
```

## 3. 詳細設計

### 3.1 クラス構成

#### 3.1.1 主要クラス

| クラス名 | 責務 |
|----------|------|
| HttpClient | HTTPリクエストの送信とレスポンス受信の主要エントリーポイント |
| HttpRequestMessage | HTTPリクエストを表現（メソッド、URI、ヘッダー、コンテンツ） |
| HttpResponseMessage | HTTPレスポンスを表現（ステータス、ヘッダー、コンテンツ） |
| HttpContent | HTTPコンテンツの抽象基底クラス |
| HttpMessageHandler | メッセージ処理の抽象基底クラス |
| SocketsHttpHandler | デフォルトのHTTPハンドラー実装 |
| DelegatingHandler | ハンドラーチェーン構築用基底クラス |

#### 3.1.2 HttpContentの派生クラス

| クラス名 | 用途 |
|----------|------|
| StringContent | 文字列コンテンツ |
| ByteArrayContent | バイト配列コンテンツ |
| StreamContent | ストリームコンテンツ |
| FormUrlEncodedContent | フォームデータ（application/x-www-form-urlencoded） |
| MultipartFormDataContent | マルチパートフォームデータ |
| JsonContent | JSONコンテンツ |

### 3.2 メソッド仕様

#### 3.2.1 HttpClient コンストラクタ

```csharp
public HttpClient();
public HttpClient(HttpMessageHandler handler);
public HttpClient(HttpMessageHandler handler, bool disposeHandler);
```

**説明**: HttpClientインスタンスを作成。カスタムハンドラーの指定が可能。

**推奨事項**:
- シングルトンまたはIHttpClientFactoryを使用
- 短命インスタンスはソケット枯渇の原因となる

#### 3.2.2 GetAsync / GetStringAsync / GetByteArrayAsync / GetStreamAsync

```csharp
public Task<HttpResponseMessage> GetAsync(string? requestUri);
public Task<HttpResponseMessage> GetAsync(Uri? requestUri);
public Task<HttpResponseMessage> GetAsync(string? requestUri, CancellationToken cancellationToken);

public Task<string> GetStringAsync(string? requestUri);
public Task<byte[]> GetByteArrayAsync(string? requestUri);
public Task<Stream> GetStreamAsync(string? requestUri);
```

**説明**: GETリクエストを送信し、レスポンスを取得する。

#### 3.2.3 PostAsync / PutAsync / DeleteAsync / PatchAsync

```csharp
public Task<HttpResponseMessage> PostAsync(string? requestUri, HttpContent? content);
public Task<HttpResponseMessage> PutAsync(string? requestUri, HttpContent? content);
public Task<HttpResponseMessage> DeleteAsync(string? requestUri);
public Task<HttpResponseMessage> PatchAsync(string? requestUri, HttpContent? content);
```

**説明**: 各HTTPメソッドでリクエストを送信。

#### 3.2.4 SendAsync

```csharp
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request);
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption);
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken);
```

**説明**: 完全にカスタマイズされたHTTPリクエストを送信。

**HttpCompletionOption**:
- `ResponseContentRead`: コンテンツ全体を読み取り後に完了
- `ResponseHeadersRead`: ヘッダー読み取り後に完了（ストリーミング用）

### 3.3 ハンドラーパイプライン

#### 3.3.1 DelegatingHandler の実装パターン

```csharp
public class LoggingHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // リクエスト前処理
        Log($"Request: {request.Method} {request.RequestUri}");

        // 次のハンドラーに委譲
        var response = await base.SendAsync(request, cancellationToken);

        // レスポンス後処理
        Log($"Response: {response.StatusCode}");

        return response;
    }
}
```

#### 3.3.2 ハンドラーチェーン構成

```
HttpClient
    │
    └── LoggingHandler (DelegatingHandler)
            │
            └── RetryHandler (DelegatingHandler)
                    │
                    └── SocketsHttpHandler (最終ハンドラー)
```

### 3.4 SocketsHttpHandler の設定

| プロパティ | デフォルト値 | 説明 |
|------------|--------------|------|
| PooledConnectionLifetime | Timeout.InfiniteTimeSpan | 接続のプール寿命 |
| PooledConnectionIdleTimeout | 1分 | アイドル接続のタイムアウト |
| MaxConnectionsPerServer | int.MaxValue | サーバーごとの最大接続数 |
| ConnectTimeout | Timeout.InfiniteTimeSpan | 接続タイムアウト |
| EnableMultipleHttp2Connections | true | HTTP/2多重接続の有効化 |
| AllowAutoRedirect | true | 自動リダイレクト |
| MaxAutomaticRedirections | 50 | 最大リダイレクト回数 |

### 3.5 HTTPバージョンサポート

| バージョン | サポート状況 | 説明 |
|------------|--------------|------|
| HTTP/1.0 | サポート | レガシープロトコル |
| HTTP/1.1 | デフォルト | 標準プロトコル |
| HTTP/2 | サポート | 多重化、ヘッダー圧縮 |
| HTTP/3 | サポート（opt-in） | QUIC/UDP ベース |

#### 3.5.1 HTTPバージョンの指定

```csharp
var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
    Version = HttpVersion.Version20,
    VersionPolicy = HttpVersionPolicy.RequestVersionOrHigher
};
```

## 4. エラー処理

### 4.1 例外一覧

| 例外 | 発生条件 |
|------|----------|
| HttpRequestException | HTTP通信エラー（接続失敗、タイムアウト等） |
| TaskCanceledException | タイムアウトまたはキャンセル |
| InvalidOperationException | 不正な操作（Dispose後の使用等） |
| UriFormatException | 不正なURI形式 |
| ArgumentNullException | 必須パラメータがnull |

### 4.2 HTTPステータスコードの処理

```csharp
// 例外をスローして処理
response.EnsureSuccessStatusCode(); // 2xx以外で例外

// 手動でチェック
if (!response.IsSuccessStatusCode)
{
    // エラー処理
}
```

### 4.3 リトライポリシー
- 一時的なエラー（5xx、タイムアウト）に対するリトライ推奨
- Pollyなどのレジリエンスライブラリとの組み合わせ
- IHttpClientFactory でのリトライハンドラー設定

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

### 5.1 HTTPS/TLS
- デフォルトでHTTPS推奨
- TLSバージョンの制御が可能
- 証明書検証のカスタマイズ

### 5.2 認証
- Basic認証: `Authorization` ヘッダー
- Bearer トークン: OAuth2/JWT
- カスタム認証ハンドラー

### 5.3 機密情報の保護
- リクエストログでの認証情報マスキング
- HTTPSの強制
- 証明書ピンニング

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

### 6.1 推奨読解順序

1. **データ構造の理解**
   - `HttpRequestMessage.cs`: リクエスト構造
   - `HttpResponseMessage.cs`: レスポンス構造
   - `HttpContent.cs`: コンテンツ抽象化

2. **エントリーポイント**
   - `HttpClient.cs`: 主要API定義
   - **コンストラクタ**: ハンドラー初期化
   - **GetAsync/PostAsync等**: 簡易メソッド群
   - **SendAsync**: 中核メソッド

3. **ハンドラー層**
   - `HttpMessageHandler.cs`: ハンドラー抽象
   - `DelegatingHandler.cs`: チェーン構築
   - `SocketsHttpHandler.cs`: デフォルト実装

4. **プロトコル実装**
   - `Http11Connection.cs`: HTTP/1.1実装
   - `Http2Connection.cs`: HTTP/2実装
   - `Http3Connection.cs`: HTTP/3実装

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

```
HttpClient.GetStringAsync(uri)
    │
    ├── GetAsync(uri, HttpCompletionOption.ResponseContentRead)
    │       │
    │       └── SendAsync(new HttpRequestMessage(HttpMethod.Get, uri), ...)
    │               │
    │               ├── PrepareRequestMessage() [リクエスト準備]
    │               │
    │               └── _handler.SendAsync(request, ...)
    │                       │
    │                       ├── [DelegatingHandler チェーン]
    │                       │
    │                       └── SocketsHttpHandler.SendAsync()
    │                               │
    │                               ├── GetConnectionAsync() [接続取得]
    │                               │       │
    │                               │       └── ConnectionPool から取得/新規作成
    │                               │
    │                               ├── SendAsyncCore() [リクエスト送信]
    │                               │       │
    │                               │       └── Http11/2/3Connection.SendAsync()
    │                               │
    │                               └── HttpResponseMessage 構築
    │
    └── response.Content.ReadAsStringAsync()
            │
            └── HttpContent.ReadAsStringAsync()
```

### 6.3 データフロー図

```
┌──────────────────┐
│ アプリケーション   │
│ HttpClient.Get() │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ HttpClient       │
│ リクエスト構築    │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ DelegatingHandler│
│ 前処理パイプライン│
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ SocketsHandler   │
│ 接続プール管理    │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐    ┌──────────────────┐
│ HTTP接続         │←→  │ リモートサーバー   │
│ TCP/TLS         │    │                  │
└────────┬─────────┘    └──────────────────┘
         │
         ▼
┌──────────────────┐
│ HttpResponse     │
│ Message構築      │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ DelegatingHandler│
│ 後処理パイプライン│
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ アプリケーション   │
│ レスポンス受信    │
└──────────────────┘
```

### 6.4 読解のコツ

#### 6.4.1 非同期パターン
HttpClientは完全非同期設計:
- すべての I/O 操作が async/await
- CancellationToken による協調キャンセル
- ConfigureAwait(false) でコンテキスト切り替え最適化

#### 6.4.2 接続プーリング
SocketsHttpHandler の接続管理:
- サーバーごとの接続プール
- Keep-Alive による接続再利用
- DNS更新のための接続寿命設定

#### 6.4.3 ハンドラーのライフサイクル
- HttpClient は長寿命推奨
- Dispose時のハンドラー解放制御
- IHttpClientFactory による管理

### 6.5 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/libraries/System.Net.Http/src/System/Net/Http/HttpClient.cs` | ソース | 主要エントリーポイント |
| `src/libraries/System.Net.Http/src/System/Net/Http/HttpRequestMessage.cs` | ソース | リクエストモデル |
| `src/libraries/System.Net.Http/src/System/Net/Http/HttpResponseMessage.cs` | ソース | レスポンスモデル |
| `src/libraries/System.Net.Http/src/System/Net/Http/HttpContent.cs` | ソース | コンテンツ抽象化 |
| `src/libraries/System.Net.Http/src/System/Net/Http/HttpMessageHandler.cs` | ソース | ハンドラー基底 |
| `src/libraries/System.Net.Http/src/System/Net/Http/DelegatingHandler.cs` | ソース | デリゲーティングハンドラー |
| `src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs` | ソース | デフォルトハンドラー |
| `src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http11Connection.cs` | ソース | HTTP/1.1接続 |
| `src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs` | ソース | HTTP/2接続 |
| `src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs` | ソース | HTTP/3接続 |
| `src/libraries/System.Net.Http/src/System/Net/Http/StringContent.cs` | ソース | 文字列コンテンツ |
| `src/libraries/System.Net.Http/src/System/Net/Http/JsonContent.cs` | ソース | JSONコンテンツ |

## 7. 使用例

### 7.1 基本的なGETリクエスト

```csharp
using var client = new HttpClient();
string content = await client.GetStringAsync("https://api.example.com/data");
Console.WriteLine(content);
```

### 7.2 POSTリクエスト（JSON）

```csharp
using var client = new HttpClient();
var data = new { Name = "Test", Value = 123 };
var response = await client.PostAsJsonAsync("https://api.example.com/items", data);
response.EnsureSuccessStatusCode();
```

### 7.3 カスタムリクエスト

```csharp
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Put, "https://api.example.com/items/1")
{
    Content = new StringContent(json, Encoding.UTF8, "application/json")
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);

var response = await client.SendAsync(request);
```

### 7.4 IHttpClientFactoryの使用

```csharp
// Startup.cs
services.AddHttpClient("api", client =>
{
    client.BaseAddress = new Uri("https://api.example.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/json");
});

// 使用箇所
public class MyService
{
    private readonly IHttpClientFactory _factory;

    public async Task<string> GetData()
    {
        var client = _factory.CreateClient("api");
        return await client.GetStringAsync("data");
    }
}
```

## 8. テスト観点

### 8.1 単体テスト観点
- 各HTTPメソッドの正常系・異常系
- タイムアウト動作の検証
- ヘッダー設定の確認
- コンテンツシリアライズ/デシリアライズ

### 8.2 結合テスト観点
- 実際のエンドポイントとの通信
- HTTPS/TLS接続の検証
- リダイレクト処理の確認
- 認証フローの検証

### 8.3 性能テスト観点
- 同時接続数の影響測定
- 接続プールの効率確認
- メモリ使用量の監視

## 9. 変更履歴

| バージョン | 日付 | 変更内容 |
|------------|------|----------|
| 1.0 | 2026-01-30 | 初版作成 |
