# 機能設計書 80-cookies

## 概要

本ドキュメントは、Nim標準ライブラリのcookiesモジュールの機能設計について記載する。本モジュールはHTTPクッキーの解析と生成のためのヘルパー関数を実装している。

### 本機能の処理概要

cookiesモジュールは、HTTPクッキーヘッダーの解析（parseCookies）とSet-Cookieヘッダーの生成（setCookie）機能を提供する。SameSite属性、Secure、HttpOnly、Max-Age、Expiresなどのクッキー属性をサポートする。

**業務上の目的・背景**：Web開発において、セッション管理やユーザー設定の保存にクッキーは不可欠である。本モジュールは、クッキーの安全な設定と解析のための標準的なAPIを提供する。

**機能の利用シーン**：
- HTTPサーバーでのクッキー解析
- Set-Cookieヘッダーの生成
- セッション管理
- ユーザー認証トークンの保存
- CSRF対策（SameSite属性）

**主要な処理内容**：
1. Cookieヘッダーの解析（parseCookies）
2. Set-Cookieヘッダーの生成（setCookie）
3. SameSite属性の設定
4. Secure/HttpOnly属性の設定
5. Max-Age/Expires属性の設定

**関連システム・外部連携**：cgi、httpclient、asynchttpserverモジュールと連携する。

**権限による制御**：なし（純粋な文字列操作）。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本モジュールはGUI/画面を持たないライブラリ機能 |

## 機能種別

Web開発 / HTTPクッキー処理 / セキュリティ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| s | string | Yes | Cookieヘッダー文字列 | - |
| key | string | Yes | クッキー名 | - |
| value | string | Yes | クッキー値 | - |
| domain | string | No | ドメイン | デフォルト: "" |
| path | string | No | パス | デフォルト: "" |
| expires | string/DateTime/Time | No | 有効期限 | デフォルト: "" |
| noName | bool | No | Set-Cookie:を省略 | デフォルト: false |
| secure | bool | No | Secure属性 | デフォルト: false |
| httpOnly | bool | No | HttpOnly属性 | デフォルト: false |
| maxAge | Option[int] | No | Max-Age属性 | デフォルト: none(int) |
| sameSite | SameSite | No | SameSite属性 | デフォルト: Default |

### 入力データソース

- Cookieヘッダー文字列（クライアントから）
- クッキー名/値/属性（サーバーから）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| StringTableRef | ref StringTable | パース済みクッキー |
| string | string | Set-Cookieヘッダー |

### 出力先

- StringTableRef経由でのクッキー値アクセス
- Set-Cookieヘッダー文字列

## 処理フロー

### 処理シーケンス

```
1. クッキー解析（parseCookies）
   ├─ スペース/タブをスキップ
   ├─ =までをキーとして取得
   ├─ ;までを値として取得
   └─ StringTableに格納
2. クッキー生成（setCookie）
   ├─ key=value形式で開始
   ├─ Domain属性追加（指定時）
   ├─ Path属性追加（指定時）
   ├─ Expires属性追加（指定時）
   ├─ Secure属性追加（指定時）
   ├─ HttpOnly属性追加（指定時）
   ├─ Max-Age属性追加（指定時）
   └─ SameSite属性追加（指定時）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{parseCookies?}
    B -->|Yes| C[スペース/タブスキップ]
    C --> D[=まで読み取り -> key]
    D --> E[;まで読み取り -> value]
    E --> F[StringTable格納]
    F --> G{終端?}
    G -->|No| C
    G -->|Yes| H[StringTable返却]
    B -->|No| I{setCookie?}
    I -->|Yes| J[key=value生成]
    J --> K{domain?}
    K -->|Yes| L[; Domain=追加]
    K -->|No| M{path?}
    L --> M
    M -->|Yes| N[; Path=追加]
    M -->|No| O{expires?}
    N --> O
    O -->|Yes| P[; Expires=追加]
    O -->|No| Q{secure?}
    P --> Q
    Q -->|Yes| R[; Secure追加]
    Q -->|No| S{httpOnly?}
    R --> S
    S -->|Yes| T[; HttpOnly追加]
    S -->|No| U{maxAge?}
    T --> U
    U -->|Yes| V[; Max-Age=追加]
    U -->|No| W{sameSite?}
    V --> W
    W -->|Yes| X[; SameSite=追加]
    W -->|No| Y[文字列返却]
    X --> Y
    Y --> Z[終了]
    H --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-80-01 | SameSite=None制約 | SameSite=NoneはSecure必須 | sameSite=None時 |
| BR-80-02 | noNameオプション | Set-Cookie:プレフィックスを省略可能 | noName=true時 |
| BR-80-03 | 大文字小文字無視 | クッキー名は大文字小文字を区別しない | parseCookies |
| BR-80-04 | 日時フォーマット | ExpiresはGMT形式 | DateTime/Time指定時 |

### 計算ロジック

Expiresフォーマット:
- DateTime/Time型の場合: `ddd',' dd MMM yyyy HH:mm:ss 'GMT'`形式に変換
- 例: `Thu, 01 Jan 2025 00:00:00 GMT`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本モジュールはデータベース操作を行わない |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| AssertionDefect | アサーションエラー | SameSite=NoneでSecure=false | Secure=trueを設定 |

### リトライ仕様

- エラー時のリトライは実装されていない

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

本モジュールは純粋な文字列処理であり、トランザクション管理は行わない。

## パフォーマンス要件

- インプレース文字列操作
- 大文字小文字無視のStringTable使用（modeCaseInsensitive）

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

- Secure属性でHTTPS限定
- HttpOnly属性でJavaScriptアクセス禁止
- SameSite属性でCSRF対策
- tip: secure=true、httpOnly=true、sameSite=Strict推奨

## 備考

- parseCookiesはCookieヘッダー（クライアント側）を解析
- Set-Cookieヘッダー（サーバー側）の解析には対応していない
- SameSite=Defaultは属性を出力しない

---

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

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

### 推奨読解順序

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

まず、SameSite列挙型を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cookies.nim | `lib/pure/cookies.nim` | SameSite列挙型（19-22行目）: SameSite属性値 |

**読解のコツ**: SameSiteはDefault、None、Lax、Strictの4値。Defaultは属性を出力しない。

#### Step 2: クッキー解析を理解する

Cookieヘッダーの解析処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cookies.nim | `lib/pure/cookies.nim` | parseCookies（24-48行目）: クッキー解析 |

**主要処理フロー**:
- **35行目**: modeCaseInsensitiveでStringTable作成
- **38行目**: スペース/タブをスキップ
- **40行目**: =までをキーとして取得
- **45行目**: ;までを値として取得
- **46行目**: StringTableに格納

#### Step 3: クッキー生成を理解する

Set-Cookieヘッダーの生成処理を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cookies.nim | `lib/pure/cookies.nim` | setCookie string版（50-71行目）: クッキー生成 |
| 3-2 | cookies.nim | `lib/pure/cookies.nim` | setCookie DateTime版（73-81行目）: 日時指定版 |

**主要処理フロー**:
- **59行目**: noName=falseなら`Set-Cookie: `プレフィックス
- **60行目**: `key=value`形式で追加
- **61-66行目**: 各属性を条件付きで追加
- **69-70行目**: SameSite=NoneはSecure必須（doAssert）
- **80行目**: DateTime/TimeをGMT形式に変換

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

```
parseCookies(s: string)
    │
    ├─ newStringTable(modeCaseInsensitive)
    │
    └─ while i < s.len
          │
          ├─ スペース/タブスキップ (38行目)
          │
          ├─ =まで読み取り → keystart..keyend
          │
          ├─ ;まで読み取り → valstart..i-1
          │
          └─ result[key] = value

setCookie(key, value, domain, path, expires, noName, secure, httpOnly, maxAge, sameSite)
    │
    ├─ [not noName] "Set-Cookie: " 追加
    │
    ├─ key=value 追加
    │
    ├─ [domain != ""] "; Domain=" 追加
    │
    ├─ [path != ""] "; Path=" 追加
    │
    ├─ [expires != ""] "; Expires=" 追加
    │
    ├─ [secure] "; Secure" 追加
    │
    ├─ [httpOnly] "; HttpOnly" 追加
    │
    ├─ [maxAge.isSome] "; Max-Age=" 追加
    │
    └─ [sameSite != Default]
          │
          ├─ [sameSite == None] doAssert secure
          │
          └─ "; SameSite=" 追加
```

### データフロー図

```
[クライアント]              [cookies モジュール]              [サーバー]

Cookie: a=1; foo=bar ──────▶ parseCookies()
                                   │
                                   ├──▶ StringTable
                                   │         │
                                   │         ├──▶ ["a"] = "1"
                                   │         │
                                   │         └──▶ ["foo"] = "bar"
                                   │
                                   ▼
                              アプリ処理
                                   │
                                   ▼
                             setCookie()
                                   │
                                   ├──▶ key=value
                                   │
                                   ├──▶ ; Domain=...
                                   │
                                   ├──▶ ; Path=...
                                   │
                                   ├──▶ ; Expires=...
                                   │
                                   ├──▶ ; Secure
                                   │
                                   ├──▶ ; HttpOnly
                                   │
                                   ├──▶ ; Max-Age=...
                                   │
                                   └──▶ ; SameSite=...
                                              │
Set-Cookie: ... ◀──────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cookies.nim | `lib/pure/cookies.nim` | ソース | クッキー解析・生成 |
| strtabs.nim | `lib/pure/strtabs.nim` | ソース | StringTable |
| times.nim | `lib/pure/times.nim` | ソース | DateTime/Time変換 |
| options.nim | `lib/pure/options.nim` | ソース | Option[int]用 |
| cgi.nim | `lib/pure/cgi.nim` | ソース | クッキー使用側 |
| httpclient.nim | `lib/pure/httpclient.nim` | ソース | クッキー使用側 |
