zudo-doc
GitHub リポジトリ

Type to search...

to open search from anywhere

Search Worker API

作成2026年4月27日Takeshi Takatsudo

大規模なドキュメントベースやAPIコンシューマー向けに、サーバーサイド検索APIを提供するスタンドアロンのCloudflare Workerです。

概要

Search Workerはpackages/search-worker/にあるサブパッケージで、Cloudflare Workerとしてデプロイされます。組み込みのクライアントサイド検索と同じMiniSearchエンジンと検索インデックスを使用しますが、Cloudflare Workersランタイム上でサーバーサイドで実行されます。

これは以下の場合に便利です:

  • ドキュメントベースがクライアントサイド検索では大きすぎる場合(フルインデックスをブラウザにダウンロードする必要がある)
  • 外部コンシューマー(ボット、インテグレーション、CLIツール)に検索APIを提供したい場合
  • プログラムによるアクセスのためにサーバーサイド検索が必要な場合

Workerはデプロイ済みのドキュメントサイトからsearch-index.jsonを取得し、5分のTTLでメモリにキャッシュします。

📝 Note

Search Workerは既存の検索の追加オプションであり、置き換えではありません。主要な検索体験は検索ダイアログ(Ctrl+K / Cmd+K)を通じたクライアントサイドMiniSearchのままです。使い分けについては使い分けガイドを参照してください。

エンドポイント

POST /
Content-Type: application/json

WorkerはルートURLで応答します。

リクエストボディ

interface SearchRequest {
  query: string;
  limit?: number;
}
フィールド必須説明
querystringはい検索クエリ文字列。空でないこと、最大500文字。
limitnumberいいえ返却する最大結果数。デフォルト:20、最大:100。

成功レスポンス (200)

interface SearchResponse {
  results: SearchResult[];
  query: string;
  total: number;
}

interface SearchResult {
  id: string;
  title: string;
  url: string;
  description: string;
  score: number;
}

例:

{
  "results": [
    {
      "id": "guides/adding-pages",
      "title": "Adding Pages",
      "url": "/docs/guides/adding-pages",
      "description": "Learn how to add new documentation pages",
      "score": 12.5
    }
  ],
  "query": "how to add a page",
  "total": 3
}

エラーレスポンス

ステータス条件
400無効なJSONボディ
400queryが空でない文字列ではない
400queryが500文字の制限を超えている
404リクエストパスが/ではない
405リクエストメソッドがPOSTではない
429レート制限超過(Retry-Afterヘッダーを含む)
500内部サーバーエラー(インデックス取得失敗等)

すべてのエラーレスポンスは{ "error": string }形式を使用します。

環境設定

変数

wrangler.tomlDOCS_SITE_URLをデプロイ済みのドキュメントサイトに設定します:

[vars]
DOCS_SITE_URL = "https://your-docs-site.example.com"
RATE_LIMIT_PER_MINUTE = "60"
RATE_LIMIT_PER_DAY = "1000"
変数デフォルト説明
DOCS_SITE_URLデプロイ済みのドキュメントサイトURL
RATE_LIMIT_PER_MINUTE60IPあたりの1分間の最大リクエスト数
RATE_LIMIT_PER_DAY1000IPあたりの1日の最大リクエスト数

Workerは${DOCS_SITE_URL}/search-index.jsonから検索インデックスを取得します。

KV名前空間

レート制限にはCloudflare KV名前空間を使用します。デプロイ前に作成してください:

cd packages/search-worker
npx wrangler kv namespace create RATE_LIMIT

返却された名前空間IDでwrangler.toml[[kv_namespaces]]idを更新します。

レート制限の動作

WorkerはCloudflareが提供するcf-connecting-ipヘッダーを使用して、IPごとのレート制限を適用します。

  • ベストエフォート適用 — KVの読み書きはアトミックではないため、同じIPからの同時リクエストが設定された制限をわずかに超える場合があります
  • フェイルオープン — KVが利用不可(障害、設定ミス)の場合、リクエストは許可されます。検索の可用性が厳密なレート制限より優先されます
  • 無効な設定RATE_LIMIT_PER_MINUTEまたはRATE_LIMIT_PER_DAYの非数値はデフォルト(60/分、1000/日)にフォールバックします
  • 429レスポンスRetry-Afterヘッダー(現在のウィンドウがリセットされるまでの秒数)を含み、CORSを通じてブラウザアクセスに公開されます

デプロイ

手動

cd packages/search-worker
pnpm install
pnpm run deploy

CI/CD

AI Chat Workerのデプロイと同様のGitHub Actionsワークフローを追加できます。packages/search-worker/内のファイルが変更された場合にmainへのプッシュでWorkerをデプロイするワークフローを設定します。

必要なGitHubシークレット:

  • CLOUDFLARE_API_TOKEN — Workers書き込み権限を持つCloudflare APIトークン
  • CLOUDFLARE_ACCOUNT_ID — CloudflareアカウントID

使い分けガイド

機能クライアントサイド検索(組み込み)Search Worker
ランタイムブラウザ(インメモリ)Cloudflare Workers
デプロイドキュメントサイトの一部独立したサービス
インデックスダウンロードフルインデックスをブラウザに送信インデックスはサーバーサイドに留まる
最適な用途小〜中規模のドキュメント大規模なドキュメント、APIコンシューマー
セットアップ不要(デフォルトで有効)Cloudflareアカウント + KV
レイテンシ即時(ローカル)ネットワークラウンドトリップ
検索設定prefix: true, fuzzy: 0.2, boost: { title: 3, description: 2 }同一

両方とも同じ検索インデックス(search-index.json)と同じMiniSearch設定を使用するため、結果は一貫しています。

リクエストフロー

  1. CORSプリフライトの処理
  2. メソッドチェック(POSTのみ)とパスチェック(/のみ)
  3. JSONパースとクエリバリデーション(必須、最大500文字)
  4. Web Crypto APIによるSHA-256でクライアントIPをハッシュ化
  5. KVに対するレート制限チェック
  6. ドキュメントサイトからsearch-index.jsonを取得(5分TTLでキャッシュ)
  7. プレフィックス、ファジー、ブースト設定でMiniSearchクエリを実行
  8. 結果を返却

サブパッケージの場所

packages/search-worker/
├── src/
│   ├── index.ts        # Workerエントリーポイント — ルーティング、バリデーション、CORS
│   ├── cors.ts         # CORSヘッダー処理
│   ├── rate-limit.ts   # KVによるIPごとのレート制限
│   ├── search.ts       # MiniSearchインデックスローダー + 検索ロジック
│   └── types.ts        # 型定義
├── wrangler.toml       # Cloudflare Worker設定
├── package.json
├── tsconfig.json
└── README.md

Revision History

AI Assistant

Ask a question about the documentation.