尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

【Bug已解决】CORS Error on https://api.anthropic.com/v1/messages API with Reacrt.js 解决方案

【Bug已解决】CORS Error on https://api.anthropic.com/v1/messages API with Reacrt.js 解决方案 【Bug已解决】CORS Error on https://api.anthropic.com/v1/messages API with Reacrt.js 解决方案一、现象长什么样你在 React原文拼写为 Reacrt.js前端里直接用fetch调 Anthropic APIfetch(https://api.anthropic.com/v1/messages, { method: POST, headers: { x-api-key: KEY, anthropic-version: 2023-06-01, content-type: application/json }, body: JSON.stringify({ model: claude-3-5-sonnet-latest, max_tokens: 256, messages: [...] }), });浏览器控制台报Access to fetch at https://api.anthropic.com/... from origin http://localhost:3000 has been blocked by CORS policyNo Access-Control-Allow-Origin header is present预检OPTIONS请求被拒你换axios、换XMLHttpRequest都一样因为问题不在库而在浏览器同源策略用 Postman / curl / 后端能成功只有浏览器前端失败。一句话api.anthropic.com没有返回Access-Control-Allow-Origin浏览器出于同源策略禁止前端 JS 直接跨域调用它——Anthropic API 本就不设计给浏览器直连。二、背景CORS跨源资源共享是浏览器的安全机制当前端页面源 A的 JS 去请求另一个源源 B的资源时浏览器会要求 B 的响应带Access-Control-Allow-Origin头否则拦截。api.anthropic.com出于安全主要是防止 API key 暴露在前端不开启 CORS。原因很硬浏览器前端代码对用户可见把x-api-key写进前端等于把密钥公开即使忽略密钥问题服务端也没返回 CORS 头浏览器照样拦Anthropic 的设计是密钥只在服务端使用前端应通过你自己的后端去调用。所以在 React 里直连 Anthropic从架构上就不被支持CORS 只是表象真正的问题是密钥不该进浏览器。三、根因根因是浏览器同源策略 服务端未开 CORS且密钥不应暴露在前端React 前端 (http://localhost:3000) - 浏览器发起跨域 fetch 到 api.anthropic.com - 浏览器先做 CORS 预检OPTIONS - 服务端未返回 Access-Control-Allow-Origin - 浏览器拦截响应 - CORS Error注意即使你手动在请求里加Access-Control-Allow-Origin也没用——这个头是服务端响应才有效的客户端设了被浏览器忽略。也不要试图在前端关 CORS那是浏览器行为前端改不了。四、最小可运行复现下面演示服务端是否有 CORS 头的判断用 Node 起一个本地后端中转正确做法// 错误浏览器前端直连会被 CORS 拦 async function badCall() { const r await fetch(https://api.anthropic.com/v1/messages, { method: POST, headers: { x-api-key: sk-..., anthropic-version: 2023-06-01 }, body: JSON.stringify({ model: claude-3-5-sonnet-latest, max_tokens: 256, messages: [] }), }); return r.json(); // CORS Error } // 正确前端只调自己的后端密钥在后端的服务端 // 前端 async function goodCall(prompt) { const r await fetch(/api/claude, { // 同源无 CORS 问题 method: POST, headers: { content-type: application/json }, body: JSON.stringify({ prompt }), }); return r.json(); }后端Node/Express示例import express from express; import Anthropic from anthropic-ai/sdk; const app express(); app.use(express.json()); const client new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }); // 密钥在服务端 app.post(/api/claude, async (req, res) { const msg await client.messages.create({ model: claude-3-5-sonnet-latest, max_tokens: 256, messages: [{ role: user, content: req.body.prompt }], }); res.json(msg); }); app.listen(3001);五、解决方案第一层最小直接修复最小修复是把 API 调用挪到服务端前端只跟你自己的同源后端通信// React 前端 export async function askClaude(prompt) { const res await fetch(/api/claude, { method: POST, headers: { content-type: application/json }, body: JSON.stringify({ prompt }), }); if (!res.ok) throw new Error(await res.text()); return res.json(); }后端用官方 SDK密钥放环境变量永不进前端如上面 Express 示例。这样无 CORS 问题前端与后端同源API key 不暴露给用户还能在服务端做限流、审计、日志。六、解决方案第二层结构化改进把前端→服务端→Anthropic的调用边界做成策略集中约束密钥只存在于服务端from dataclasses import dataclass import os from typing import Dict dataclass(frozenTrue) class AnthropicCorsReactPolicy: 前后端调用策略密钥只在服务端前端只调同源后端。 规则 - 前端禁止出现 x-api-key / ANTHROPIC_API_KEY - 前端只请求同源后端路径如 /api/claude - 后端用 SDK 调用 Anthropic密钥取自环境变量 backend_route: str /api/claude def frontend_call_shape(self) - Dict[str, str]: # 前端应只发到同源后端不带任何密钥头 return {url: self.backend_route, auth: same-origin-session} def backend_must_use_env_key(self) - str: key os.environ.get(ANTHROPIC_API_KEY, ) if not key: raise RuntimeError(后端必须从环境变量读取 ANTHROPIC_API_KEY禁止硬编码) return ok def demo() - None: policy AnthropicCorsReactPolicy() print(policy.frontend_call_shape()) # 只到同源后端 # policy.backend_must_use_env_key() if __name__ __main__: demo()七、解决方案第三层断言 / CI 守护import os import pytest from your_module import AnthropicCorsReactPolicy def test_frontend_no_key_header(): policy AnthropicCorsReactPolicy() shape policy.frontend_call_shape() assert x-api-key not in str(shape) assert shape[url].startswith(/api/) def test_backend_requires_env_key(monkeypatch): policy AnthropicCorsReactPolicy() monkeypatch.delenv(ANTHROPIC_API_KEY, raisingFalse) with pytest.raises(RuntimeError): policy.backend_must_use_env_key() def test_backend_ok_with_env(monkeypatch): policy AnthropicCorsReactPolicy() monkeypatch.setenv(ANTHROPIC_API_KEY, sk-x) assert policy.backend_must_use_env_key() ok def test_frontend_targets_same_origin(): policy AnthropicCorsReactPolicy() assert anthropic.com not in policy.frontend_call_shape()[url]CI 里加一条扫描前端打包产物若发现sk-ant-或x-api-key字面量则构建失败防止密钥泄露。八、排查清单是否在浏览器前端直连api.anthropic.comCORS 必拦且密钥会泄露。是否把x-api-key写进了前端代码立即移除密钥只在服务端。是否改用前端→同源后端→Anthropic的三段式这是正解。后端是否用官方 SDK 环境变量密钥不要用fetch在前端带 key。是否在前端强行关 CORS那是浏览器行为改不了别浪费时间。CI 是否扫描前端产物防密钥硬编码九、小结React 前端直连api.anthropic.com报 CORS Error根因是 Anthropic 出于安全不开启 CORS也本就不该浏览器直连而把 API key 写进前端会直接泄露密钥。最小修复是改为前端→同源后端→Anthropic前端只调你自己的后端、密钥只在服务端用 SDK 调用结构化做法是抽成AnthropicCorsReactPolicy强制前端无密钥、只走同源后端最后用 pytest CI 扫描守护密钥不进前端、前端只请求同源路径既解决 CORS 又守住安全底线。
返回列表