# 機能設計書 76-Fetch API

## 概要

本ドキュメントは、BunのFetch API機能の機能設計を記述する。Fetch APIは、Web標準に準拠したHTTP/HTTPSリクエストを行うためのAPIを提供する。

### 本機能の処理概要

BunのFetch APIは、WHATWG Fetch Standardに準拠したHTTPクライアント機能を提供する。非同期でHTTPリクエストを実行し、Responseオブジェクトを返す。HTTP/1.1、HTTP/2、TLS/SSLをサポートし、プロキシ、リダイレクト、タイムアウトなどの機能も提供する。

**業務上の目的・背景**：外部APIとの通信、Webリソースの取得、REST APIクライアントの実装など、HTTPベースの通信が必要なすべての場面で使用される。ブラウザのFetch APIと同じインターフェースを提供することで、フロントエンドとバックエンドでコードを共有可能。

**機能の利用シーン**：
- REST API呼び出し
- Webページやリソースのダウンロード
- ファイルアップロード
- Webhookの送信
- マイクロサービス間通信
- 外部サービスとの連携

**主要な処理内容**：
1. URLとオプションを指定してfetch()を呼び出し
2. HTTPリクエストの構築（ヘッダー、ボディ、メソッド）
3. 非同期でHTTP通信を実行
4. レスポンスをResponseオブジェクトとして返却
5. レスポンスボディをjson(), text(), arrayBuffer()等で取得

**関連システム・外部連携**：Bunの内部HTTPクライアント（http.AsyncHTTP）を使用。TLS/SSL、プロキシサーバー、DNSリゾルバと連携。

**権限による制御**：特に権限による制御は行われない。ネットワークアクセスが可能なすべてのコードから利用可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | コマンドライン/API経由での利用（画面なし） |

## 機能種別

HTTP通信 / 非同期I/O

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| input | string / URL / Request | Yes | リクエストURL | 空文字列不可 |
| init | RequestInit | No | リクエストオプション | - |

### RequestInitオプション

| オプション | 型 | 説明 |
|-----------|-----|------|
| method | string | HTTPメソッド（GET, POST等） |
| headers | Headers / object | リクエストヘッダー |
| body | string / Blob / FormData / URLSearchParams / ReadableStream | リクエストボディ |
| mode | string | CORSモード（cors, no-cors, same-origin） |
| credentials | string | 認証情報（omit, same-origin, include） |
| cache | string | キャッシュモード |
| redirect | string | リダイレクト処理（follow, error, manual） |
| referrer | string | リファラー |
| referrerPolicy | string | リファラーポリシー |
| integrity | string | サブリソースインテグリティ |
| keepalive | boolean | 接続維持 |
| signal | AbortSignal | 中断シグナル |
| proxy | string | プロキシURL |
| timeout | number | タイムアウト（ms） |
| tls | object | TLS設定 |

### 入力データソース

API呼び出し時の引数として直接指定。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| response | Promise<Response> | HTTPレスポンス |

### Responseオブジェクトプロパティ

| プロパティ | 型 | 説明 |
|-----------|-----|------|
| ok | boolean | ステータスコードが200-299か |
| status | number | HTTPステータスコード |
| statusText | string | ステータステキスト |
| headers | Headers | レスポンスヘッダー |
| url | string | 最終URL |
| redirected | boolean | リダイレクトされたか |
| type | string | レスポンスタイプ |
| body | ReadableStream | レスポンスボディストリーム |
| bodyUsed | boolean | ボディが使用済みか |

### Responseオブジェクトメソッド

| メソッド | 説明 |
|---------|------|
| json() | JSONとしてパース |
| text() | テキストとして取得 |
| arrayBuffer() | ArrayBufferとして取得 |
| blob() | Blobとして取得 |
| formData() | FormDataとして取得 |
| clone() | レスポンスをクローン |

### 出力先

Promiseとして返却。

## 処理フロー

### 処理シーケンス

```
1. fetch()呼び出し
   └─ URL、オプションの検証
2. FetchTaskletの作成
   └─ 非同期タスクを生成
3. HTTPリクエストの構築
   └─ ヘッダー、ボディ、メソッドを設定
4. AsyncHTTPでリクエスト実行
   └─ TLS/プロキシ処理を含む
5. レスポンス受信
   └─ ステータス、ヘッダー、ボディを取得
6. Responseオブジェクト返却
   └─ Promiseをresolve
```

### フローチャート

```mermaid
flowchart TD
    A[fetch] --> B{引数チェック}
    B -->|エラー| C[Promise reject]
    B -->|OK| D[URL解析]
    D --> E{URLスキーム?}
    E -->|data:| F[dataURLResponse]
    E -->|http/https| G[FetchTasklet作成]
    E -->|その他| C
    F --> H[Promise resolve]
    G --> I[AsyncHTTP開始]
    I --> J{成功?}
    J -->|Yes| K[Response作成]
    J -->|No| L[エラー処理]
    K --> H
    L --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-76-01 | GET/HEAD/OPTIONSにボディ禁止 | GETなどのメソッドではボディを設定不可 | 常時 |
| BR-76-02 | プロキシとUnixソケット排他 | プロキシ使用時はUnixソケット不可 | 常時 |
| BR-76-03 | 空URLエラー | 空のURL文字列は許可しない | 常時 |
| BR-76-04 | data:URLサポート | data: URLはローカルで処理 | 常時 |

### 計算ロジック

なし

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

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

なし（データベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TypeError | Error | 引数なし/空URL | 有効なURLを指定 |
| TypeError | Error | GET/HEAD/OPTIONSにボディ | ボディを削除 |
| TypeError | Error | プロキシ+Unixソケット | どちらかを削除 |
| AbortError | Error | AbortSignalで中断 | 意図的な中断 |
| NetworkError | Error | ネットワークエラー | 接続を確認 |

### リトライ仕様

API側でのリトライ機能なし（呼び出し側で制御）

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

なし

## パフォーマンス要件

- 非同期IOでメインスレッド非ブロック
- コネクションプーリング
- HTTP/2対応
- preconnect()で事前接続

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

- TLS/SSL暗号化をサポート
- 証明書検証（rejectUnauthorized）
- カスタム証明書検証（checkServerIdentity）
- AbortSignalで長時間リクエストを中断可能

## 備考

- fetch.preconnect()で事前接続が可能
- S3 URLもサポート
- Node.js HTTP互換レイヤーも利用可能

---

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

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

### 推奨読解順序

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

fetch関数の入り口を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | fetch.zig | `src/bun.js/webcore/fetch.zig` | エラーメッセージ定義（1-59行目） |
| 1-2 | fetch.zig | `src/bun.js/webcore/fetch.zig` | Bun__fetch_関数（165-200行目） |

**読解のコツ**: fetch_error_*定数でエラーメッセージを定義。Bun__fetch_がJSからのエントリーポイント。

**主要処理フロー**:
1. **165-170行目**: Bun__fetch_でfetchImplを呼び出し
2. **181-200行目**: fetchImplで引数検証、エラー時はrejectedPromise

#### Step 2: data:URL処理を理解する

data: URLの特殊処理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | fetch.zig | `src/bun.js/webcore/fetch.zig` | dataURLResponse関数（63-96行目） |

**主要処理フロー**:
- **63-96行目**: data: URLをデコードしてBlobを作成、Responseを返却

#### Step 3: FetchTaskletを理解する

非同期HTTPリクエストの管理。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FetchTasklet.zig | `src/bun.js/webcore/fetch/FetchTasklet.zig` | FetchTasklet構造体（1-100行目） |

**主要処理フロー**:
- **1-60行目**: フィールド定義（http, result, metadata, request_body等）
- **62-86行目**: 参照カウント管理（ref/deref）
- **88-100行目**: HTTPRequestBody union型

#### Step 4: preconnect機能を理解する

事前接続機能。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | fetch.zig | `src/bun.js/webcore/fetch.zig` | Bun__fetchPreconnect_関数（102-145行目） |

**主要処理フロー**:
- **102-145行目**: URL検証、HTTP/HTTPS/S3のみ許可、AsyncHTTP.preconnect呼び出し

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

```
fetch(url, options)
    │
    ├─ Bun__fetch_() [エントリーポイント]
    │      └─ fetchImpl()
    │             ├─ 引数検証
    │             ├─ URL解析
    │             └─ FetchTasklet作成
    │
    ├─ data: URL
    │      └─ dataURLResponse()
    │             ├─ DataURL.decodeData()
    │             └─ Response作成
    │
    └─ http/https URL
           └─ FetchTasklet
                  ├─ http.AsyncHTTP
                  ├─ Response作成
                  └─ Promise resolve/reject

fetch.preconnect(url)
    │
    └─ Bun__fetchPreconnect_()
           └─ http.AsyncHTTP.preconnect()
```

### データフロー図

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

fetch(url, opts)   ───▶  fetchImpl()
                         ├─ URL解析
                         ├─ RequestInit解析
                         └─ FetchTasklet作成
                                │
                                ▼
                         http.AsyncHTTP
                         ├─ TLS処理
                         ├─ プロキシ処理
                         └─ HTTP通信
                                │
                                ▼
                         Response作成              ───▶   Promise<Response>
                         ├─ status
                         ├─ headers
                         └─ body

response.json()    ───▶  ボディ取得
response.text()          └─ パース                ───▶   Promise<T>
response.blob()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| fetch.zig | `src/bun.js/webcore/fetch.zig` | ソース | fetch関数エントリーポイント |
| FetchTasklet.zig | `src/bun.js/webcore/fetch/FetchTasklet.zig` | ソース | 非同期タスク管理 |
| Response.zig | `src/bun.js/webcore/Response.zig` | ソース | Responseオブジェクト |
| Request.zig | `src/bun.js/webcore/Request.zig` | ソース | Requestオブジェクト |
| AsyncHTTP.zig | `src/http/` | ソース | HTTP通信実装 |
| Blob.zig | `src/bun.js/webcore/Blob.zig` | ソース | Blobオブジェクト |
