从 Cloudflare Workers 调用 CAPTCHA API
使用 Worker 通过服务端 fetch 调用 solvethree 的任务 API。将工作区 API 密钥存储在密钥绑定中,在 Worker 中固定目标输入,并且仅向获授权的应用调用方返回任务响应。
本页内容
配置目标和密钥
首先,在控制台中为工作区激活目标站点的配置文件。发送主机名和操作不会创建配置文件。如果尚未完成这一前提条件,请参阅站点配置文件设置。
SOLVETHREE_API_KEY:工作区 API 密钥,存储为 Worker 密钥。INTEGRATION_KEY:一个独立密钥,应用调用方必须通过x-integration-key发送。SOLVETHREE_PROXY:用于求解的代理 URL。如果包含凭据,请将其存储为密钥。CAPTCHA_SITE:目标主机名,而不是完整 URL。
此示例将操作固定为 login,并提供一个代理。请修改这些已部署的输入以适配你的集成;不要接受调用方传入的任意目标输入。省略 recaptchaType 时,API 默认使用 reCAPTCHA Enterprise v3。
集成密钥应在受信任的应用调用方与 Worker 之间使用,不要放入公开分发的浏览器代码中。它是共享凭据,不提供逐用户的任务授权。
创建和获取任务
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.
创建任务
向 Worker 发送 POST 请求,并附带
x-integration-key和x-request-id。请求 ID 应包含 1–64 个 ASCII 字母、数字、下划线或连字符。Worker 根据其配置的目标和代理构建任务请求体,不使用调用方提供的请求体。 - 2.
保存任务 ID
Worker 返回求解服务的 JSON 响应。请保存返回的任务 ID,并保留创建任务时使用的请求 ID。
- 3.
获取结果
向 Worker 发送 GET 请求,在
id查询参数中传入任务 ID,并使用相同的集成密钥请求头。处理程序会验证 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,而不是无关的浏览器请求头。任务就绪表示 solvethree 已生成解决方案;是否被接受取决于随后向目标发送的请求。
运行您的第一个任务。
使用 $5 工作区额度开始体验。