Cloudflare WorkersからCAPTCHA APIを呼び出す

著者:solvethree読了時間:1分

Worker からサーバー側の fetch を使って solvethree のタスク API を呼び出します。ワークスペースの API キーはシークレットバインディングに保存し、送信先の入力値は Worker 内で固定し、タスクのレスポンスは許可されたアプリケーションの呼び出し元にのみ返してください。

このページの内容

送信先とシークレットを設定する

まず、コンソールで対象サイトのプロファイルをワークスペース向けに有効化してください。ホスト名とアクションを送信しても、プロファイルは作成されません。この前提条件を満たしていない場合は、サイトプロファイルの設定を参照してください。

  • SOLVETHREE_API_KEY: Worker のシークレットとして保存する、ワークスペースの API キー。
  • INTEGRATION_KEY: アプリケーションの呼び出し元が x-integration-key で送信する必要がある、別のシークレット。
  • SOLVETHREE_PROXY: 解答生成に使用するプロキシ URL。認証情報を含む場合はシークレットとして保存してください。
  • CAPTCHA_SITE: 完全な URL ではなく、対象のホスト名です。

この例では、アクションを login に固定し、プロキシを 1 つ指定しています。デプロイするこれらの入力値は、実際の連携に合わせて変更してください。呼び出し元から任意の送信先入力を受け付けないでください。recaptchaType を省略すると、API はデフォルトで reCAPTCHA Enterprise v3 を使用します。

連携キーは、信頼できるアプリケーションの呼び出し元と Worker の間で使用し、公開配布するブラウザコードには含めないでください。これは共有の認証情報であり、ユーザーごとのタスク認可ではありません。

タスクを作成・取得する

Worker · 認証付きの作成・取得REST呼び出し
export default {
  async fetch(request, env) {
    if (!env.INTEGRATION_KEY || request.headers.get('x-integration-key') !== env.INTEGRATION_KEY) {
      return new Response('Unauthorized', { status: 401 });
    }
    const url = new URL(request.url);
    const headers = { Authorization: `Bearer ${env.SOLVETHREE_API_KEY}`, 'Content-Type': 'application/json' };
    let response;
    if (request.method === 'POST') {
      const requestId = request.headers.get('x-request-id');
      if (!requestId || !/^[A-Za-z0-9_-]{1,64}$/.test(requestId)) return new Response('Provide X-Request-ID', { status: 400 });
      response = await fetch('https://api.solvethree.com/v1/tasks?waitMs=0', {
        method: 'POST', headers, redirect: 'error', signal: AbortSignal.timeout(20000),
        body: JSON.stringify({ site: env.CAPTCHA_SITE, action: 'login', proxy: env.SOLVETHREE_PROXY, requestId }),
      });
    } else if (request.method === 'GET') {
      const id = url.searchParams.get('id');
      if (!id || !/^[A-Za-z0-9_-]{1,128}$/.test(id)) return new Response('Provide a valid id', { status: 400 });
      response = await fetch(`https://api.solvethree.com/v1/tasks/${encodeURIComponent(id)}?waitMs=15000`, {
        headers, redirect: 'error', signal: AbortSignal.timeout(25000),
      });
    } else return new Response('Use POST or GET', { status: 405 });
    if (!response.ok) return Response.json({ error: 'Solver API request failed', status: response.status }, { status: response.status });
    return Response.json(await response.json(), { headers: { 'Cache-Control': 'no-store' } });
  },
};
// Store keys in Worker secret bindings. The task proxy field does not add a
// generic HTTP proxy option to Workers fetch; another client must submit through it.
  1. 1.

    タスクを作成する

    x-integration-key と x-request-id を付けて Worker に POST を送信します。リクエスト ID には、ASCII の英字、数字、アンダースコア、ハイフンからなる 1–64 文字を使用してください。Worker は、設定済みの送信先とプロキシからタスクの本文を構築し、呼び出し元が指定した本文は使用しません。

  2. 2.

    タスク ID を保存する

    Worker はソルバーの JSON レスポンスを返します。返されたタスク ID を保存し、作成に使用したリクエスト ID も保持してください。

  3. 3.

    結果を取得する

    タスク ID を id クエリパラメーターに指定し、同じ連携キーヘッダーを付けて Worker に GET を送信します。ハンドラーは ID の構文を検証し、そのタスクを solvethree から取得します。

上流への両方のリクエストは、ワークスペースのキーで認証します。ハンドラーは、成功以外の HTTP ステータスコードを汎用的なエラー本文とともに転送し、成功した JSON レスポンスに Cache-Control: no-store を設定します。共有の連携キーによる確認以外に、タスクの所有権は確認しません。個別のユーザーに取得機能を公開する前に、その認可を追加してください。

別のタスクを作成せずにタイムアウトを処理する

作成時は waitMs=0 を使用し、fetch のタイムアウトは 20 秒です。取得時は waitMs=15000 を使用し、fetch のタイムアウトは 25 秒です。これらは個々の HTTP 呼び出しの上限であり、タスク全体の存続期間の上限ではありません。

タスク ID を受け取る前に作成がタイムアウトした場合は、同じリクエスト ID で同じタスクリクエストを繰り返してください。タスクが作成済みであれば、既存のタスクを復旧できます。接続が失敗したという理由だけで新しい ID を生成しないでください。最初のリクエストは、すでに solvethree に届いている可能性があります。入力を変更して同じ ID を再利用すると、競合になります。

この例では、タイムアウトを含む fetch の例外を捕捉しません。呼び出し元に構造化されたエラーレスポンスが必要な場合は例外処理を追加してください。ただし、復旧に使えるようリクエスト ID は保持してください。

  • pending または solving: 呼び出し元で設定した全体の期限内で、同じタスクを再度取得します。
  • ready: 解答を利用できます。ポーリングを停止し、送信クライアントに渡します。
  • failed: ポーリングを停止し、errorCode と error を確認します。別のタスクを作成する前に、報告された問題を修正してください。

HTTP エラーと、ステータスが failed のタスクは、異なる種類の失敗です。ハンドラーは最初に HTTP ステータスを確認しますが、呼び出し元は成功レスポンス内のタスクステータスも確認する必要があります。診断については、CAPTCHA API エラーを参照してください。

プロキシを利用できるクライアントから送信する

この Worker の例が呼び出すのは solvethree のみです。タスクの proxy フィールドは、ソルバーに使用するプロキシを指定するものであり、Worker のネットワーク経路は変更しません。Workers の fetch には、汎用的なプロキシ URL オプションはありません。

準備できた解答を、同じプロキシ経由で意図した送信先に送信できるクライアントに渡してください。無関係なブラウザヘッダーではなく、解答とともに返された userAgent と secChUa を使用します。タスクが ready になったことは、solvethree が解答を生成したことを意味します。受理されるかどうかは、その後の送信先へのリクエストによって決まります。

最初のタスクを実行しましょう。

$5のワークスペースクレジットで始められます。

ワークスペースを作成
Cloudflare WorkersからCAPTCHA APIを呼び出す · solvethree