网页调用大模型 API 报 CORS?按预检、后端代理和 Key 边界排查
网页调用大模型 API 报 CORS,先确认浏览器请求发给谁,再分别检查预检和实际响应。用于公开应用的上游秘密 Key 应保留在自有后端,由后端调用模型接口。curl 成功、OPTIONS 返回 204、页面收到过文字,都不能单独证明整条链路正常。 本文给出定位顺序和记录模板;没有测试任何云岚API上游的跨源策略。
先画出浏览器、自己的后端和上游
建议把公开应用分成两段:浏览器 → 自有 /api/ai → 上游模型 API。浏览器提交业务输入和应用登录凭据;后端检查权限、输入与额度,再从服务端配置读取上游 Key。前端与 /api/ai 同源时,这一段无需跨源许可;若协议、主机或端口不同,由自有后端处理允许来源。服务端到上游的请求不受浏览器 CORS 检查约束,但仍可能认证失败或超时。MDN 的 CORS 定义
后端应固定允许的上游、接口与模型范围,限制输入大小、频率和用户用量,不接受浏览器传入任意目标 URL 后直接转发。自有后端也不能做成匿名、无限额的公共代理。这是本文的部署边界;不是一个可直接开放的代理程序。
curl 正常,为什么 fetch 仍然失败?
curl 不执行浏览器同源访问规则。它成功只能证明该次请求在其网络、地址和凭据条件下得到结果,不能验证网页的来源是否获准读取响应。跨源 JSON POST 或带 Authorization 的请求通常需要浏览器先发 OPTIONS;预检缓存也可能让本次看不到 OPTIONS。
打开开发者工具的 Network 面板,保留一次失败请求,按下表逐层记录。仅有 TypeError: Failed to fetch 不足以断定根因;同时看控制台具体信息,排除地址、TLS、混合内容或网络错误。
| 检查层 | 记录什么 | 能下什么结论 |
|---|---|---|
| 请求地址 | 页面 origin、Request URL、最终跳转地址 | 确认是否跨源、是否误打到静态页 |
| OPTIONS | 请求方法/请求头名单,响应状态与允许来源、方法、头 | 200/204 本身不代表许可匹配 |
| 实际 POST | 是否发出、状态、响应类型、允许来源 | 预检通过后,实际响应仍须满足跨源读取条件 |
| 自有后端 | 同一次请求的脱敏追踪号、应用鉴权和上游结果 | 区分应用拒绝、上游错误与响应转发问题 |
不要只改 OPTIONS。实际 POST 的错误响应若缺少必要的 CORS 响应头,浏览器脚本也可能无法读取其中的错误。此时在后端日志核对真实状态,而不是把所有失败都归因于 Key。MDN 的预检与实际响应示例
自有后端需要返回哪些跨源信息?
假设页面来自 https://app.example.com,自有接口在 https://api.example.com。下面只描述检查项,不代表任何在线接口的配置。预检不应触发模型调用;浏览器的 CORS 预检按规范不带凭据,不要要求它携带登录 Cookie,实际 POST 仍需鉴权:
- OPTIONS 的
Access-Control-Allow-Origin应允许该页面来源,Access-Control-Allow-Methods应允许实际方法,Access-Control-Allow-Headers应覆盖浏览器请求的非简单头。 - 实际响应也需要正确的
Access-Control-Allow-Origin;应用成功和错误分支都要检查。不要无条件回显任意 Origin。 - 如果使用跨源 Cookie 登录,还需核对客户端
credentials、服务端Access-Control-Allow-Credentials和 Cookie 策略。带凭据时,允许来源不能用*。MDN 凭据请求说明
能读到响应以后,再检查 response.ok、内容类型和业务结果。fetch 遇到可读取的 HTTP 404 等错误响应,并不会仅因为状态码自动 reject。MDN Fetch 状态检查
本地正常,上线失败,先查构建和路由
Vite 的 server.proxy 配置属于开发服务器。构建成静态文件后,生产环境仍需实际部署 /api/ai 后端或转发路由;不能把开发配置当成上线完成的证据。若请求拿到 HTML 首页或 404,先核对生产路由。Vite 服务端配置
.env 文件不等于秘密保管区。Vite 会把供客户端使用的 VITE_* 值打入前端代码;将上游 Key 换成环境变量名,仍可能在产物或网络请求里暴露。应检查构建产物和浏览器请求是否含上游 Key,记录“有/无”,不要把值复制进排查表。Vite 环境变量说明
怎样确认修复完成?
下载浏览器 API 请求边界与验收记录包,先填写来源和两段请求的负责人,再用你有权测试的环境复核:允许来源能读取成功与错误结果;未登录用户不会触发上游调用;超出应用额度的请求被拒绝;浏览器不携带上游秘密 Key。包中案例均为人工场景,没有真实请求或模型结果。
云岚API接入的地址与协议先按 Base URL 配置说明核对;已确认可读取的 401、429 等错误继续看通用报错排查。若返回流式内容,再按 SSE 完成状态验收检查终止事件,不能把出现文字当作完成。
常见问题
在前端加 Access-Control-Allow-Origin 有用吗?
没有。它是服务端响应头,应在接收浏览器请求的服务端配置。给请求随意加头还可能增加预检条件,不能替目标服务授权。
mode: no-cors 可以临时读取模型结果吗?
不适合。其跨源响应是 opaque,JavaScript 无法读取响应体和头,状态显示为 0;这不能用于正常解析模型 JSON。MDN Fetch 响应类型
dangerouslyAllowBrowser 能解决 CORS 和 Key 泄露吗?
不能。它只允许 OpenAI SDK 在浏览器环境运行,不会隐藏 Key,也不会替服务端修改跨源响应头。官方 SDK 默认禁用浏览器支持,就是为了避免暴露秘密凭据。OpenAI Node SDK
只允许自己的 Origin,后端就不用登录校验了吗?
仍需校验用户身份与权限;浏览器来源限制不能替代服务端鉴权。使用 Cookie 会话的接口,还应按框架实施 CSRF 防护,不能把 CORS 当作完整的防护方案。MDN CSRF 防护
官方资料核对日期:2026-10-24。本文提供通用浏览器与后端诊断流程,不承诺特定模型、渠道或托管平台的跨源兼容性。
