三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

如何在 Cloudflare Workers 中调用第三方 API 遇到 CORS 怎么解决

如何在 Cloudflare Workers 中调用第三方 API 遇到 CORS 怎么解决

最推荐的做法是在 Worker 代码中直接给返回给浏览器的响应添加 CORS 响应头,而不是试图修改第三方 API 的设置,因为 Worker 作为服务端中间层不受浏览器 CORS 策略限制。

先说结论:Cloudflare Workers 发起的后端请求不会触发 CORS 报错,报错通常是因为浏览器访问 Worker 时缺少响应头,需在 Worker 返回的 Response 中手动设置 Access-Control 相关 header。

  • 先确认:检查浏览器控制台报错是发生在浏览器请求 Worker 阶段,还是 Worker 请求第三方 API 阶段。
  • 先处理:在 Worker 代码中构建 Response 对象时,写入 Access-Control-Allow-Origin 等头部信息。若涉及凭证,严禁使用通配符 *。
  • 再验证:发送 OPTIONS 预检请求,确认 Worker 是否正确放行跨域方法。

命令速用版

如果你希望快速修复,可以在 Worker 脚本中使用现代模块语法,统一给响应添加 CORS 头。以下是一个最小可用的代码片段,包含错误处理和动态 Origin 匹配:

export default {async fetch(request, env, ctx) {// 获取请求源,用于动态匹配 CORSconst origin = request.headers.get('Origin') || '*';// 处理预检请求if (request.method === 'OPTIONS') {return new Response(null, {headers: {'Access-Control-Allow-Origin': origin,'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS','Access-Control-Allow-Headers': 'Content-Type, Authorization','Access-Control-Max-Age': '86400',},})}try {// 调用第三方 APIconst response = await fetch('https://api.example.com/data')// 创建新 Headers 对象,避免继承不必要的敏感头const newHeaders = new Headers(response.headers);newHeaders.set('Access-Control-Allow-Origin', origin);newHeaders.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');// 若前端需要凭证,需显式允许且 Origin 不能为 *// newHeaders.set('Access-Control-Allow-Credentials', 'true'); return new Response(response.body, {status: response.status,headers: newHeaders});} catch (err) {// 捕获第三方 API 超时或失败,防止 Worker 抛出未捕获异常return new Response('External API Error', { status: 502 });}}
}

注意:若前端请求携带凭证,Access-Control-Allow-Origin 严禁使用 *,必须动态匹配请求头中的 Origin。

为什么会这样

CORS(跨域资源共享)是浏览器的安全机制,只限制运行在浏览器环境下的 JavaScript 代码。当你的前端页面直接请求第三方 API 时,浏览器会检查响应头,如果没有允许的标识就会拦截。

Cloudflare Workers 运行在边缘服务器上,属于服务端环境。Worker 向第三方 API 发起 fetch 请求时,不受浏览器 CORS 策略约束,可以直接获取数据。问题通常出在第二步:当 Worker 把数据返回给浏览器时,浏览器认为这是跨域请求(前端域名与 Worker 域名不同),因此要求 Worker 的响应中必须包含 CORS 允许头。

分步处理

第一步:定位报错来源
打开浏览器开发者工具的 Network 面板,找到红色的请求。如果报错是 Access-Control-Allow-Origin 且请求 URL 是你的 Worker 域名,说明需要在 Worker 代码中加头。如果请求 URL 是第三方 API 域名且由前端直接发起,说明你需要把请求改为先发给 Worker。

第二步:修改 Worker 代码
采用现代 export default 语法重构 Worker。在返回 Response 对象前,使用 headers.set 添加头部。如果需要支持凭证(cookies),Access-Control-Allow-Origin 不能为 *,必须指定具体域名,且需添加 Access-Control-Allow-Credentials: true

第三步:处理预检请求
某些请求(如携带自定义头或使用 PUT/DELETE 方法)会先发送 OPTIONS 请求。确保你的代码能识别 request.method === 'OPTIONS' 并直接返回 200 状态码及相应的 Allow 头,不要将 OPTIONS 请求转发给第三方 API。

第四步:增加异常捕获
在调用第三方 API 的 fetch 外部包裹 try-catch 块。防止第三方 API 超时或返回 5xx 错误导致 Worker 进程崩溃或返回不友好的默认错误页。

怎么验证是否生效

浏览器控制台检查
刷新页面,观察 Network 面板中原本报错的请求是否状态码变为 200 且没有 CORS 红色报错。点击请求详情,查看 Response Headers 中是否包含 Access-Control-Allow-Origin

命令行验证
使用 curl 模拟预检请求,检查头部返回情况:

curl -v -X OPTIONS -H "Origin: https://your-frontend.com" https://your-worker.workers.dev

确认返回头中包含 Access-Control-Allow-MethodsAccess-Control-Allow-Origin

常见坑

1. 通配符与凭证冲突
如果前端请求设置了 credentials: 'include',Worker 响应头中的 Access-Control-Allow-Origin 不能是 *,必须与请求头中的 Origin 一致,否则浏览器会直接拦截请求。

2. 缓存导致的预检失败
浏览器会缓存 OPTIONS 预检结果。如果修改了 Worker 代码但浏览器仍报错,尝试硬刷新或清除缓存。可以在 Worker 响应中添加 Access-Control-Max-Age 控制缓存时间。

3. 第三方 API 的 CORS 限制
虽然 Worker 请求第三方 API 不受浏览器 CORS 限制,但部分 API 服务端会校验 Referer 或 Origin。如果遇到 403 Forbidden,可能需要在 Worker 请求第三方时伪造或移除相关头部,而不是解决 CORS 问题。

4. 响应头修改无效
如果直接返回 fetch 的结果,某些只读头部可能无法修改。建议使用 new Headers(response.headers) 克隆后修改,再构建新的 Response 对象。

5. 未处理外部异常
若第三方 API 超时,Worker 默认可能抛出异常导致请求中断。务必使用 try-catch 捕获外部 fetch 错误,并返回合理的 HTTP 状态码(如 502)。

原文链接:https://www.zjcp.cc/ask/11380.html

← 返回列表