
Cloudflare Agents 跨域通信实战React 客户端与 Worker Agent 的 WebSocket/HTTP 完整接入指南【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents跨域Cross-Domain是 Web 前端接入 Agent 后端时最常踩的坑浏览器出于同源策略会拦截来自不同端口、不同域名下的 WebSocket 升级请求与 HTTP 响应导致 Agent 消息发出去却收不到。本指南以 examples/cross-domain 为例讲解如何在 React 客户端与 Cloudflare Worker Agent 运行在不同域时打通 WebSocket 实时通信与 HTTP 请求——核心结论只有一句话务必给routeAgentRequest传入cors: true。读完本文你将掌握跨域场景下 Worker 端 CORS 配置、鉴权中间件接入以及前端useAgent的静态与异步两种鉴权连接方式。示例概览一前端一 Worker 的跨域拓扑示例由两个独立进程组成各自运行在不同的域本例为不同的本地端口生产环境则对应不同的域名React 客户端Vite 开发服务器默认运行在http://localhost:5173页面代码见 src/client.tsxWorker 服务端Wrangler 本地开发服务器运行在http://localhost:8787Agent 实现见 src/server.ts。浏览器将5173与8787视为两个不同的源origin这正是触发 CORS 与 WebSocket 握手校验的典型场景。客户端的host明确指向 Worker 地址其实现也在 UI 中直接展示了两端拓扑见 src/client.tsxClient: http://localhost:5173当前页面 Server: http://localhost:8787不同端口一键启动两端的方式来自 package.json 的start脚本用concurrently同时拉起 Vite 与 Wrangler并保证任一进程退出时杀掉另一个npm i npm start等价于分别执行# 终端 A前端开发服务器 npx vite dev # 终端 BAgent Worker 本地开发服务器 npx wrangler dev服务端cors: true 与 CORS 预检处理routeAgentRequest 的 cors 选项README 的 tl;dr 指出跨域能否成功关键在于调用routeAgentRequest时传入cors: true。routeAgentRequest是agents包提供的核心路由函数用于把进入 Worker 的请求分发给对应的 AgentDurable Object。其cors选项支持boolean | HeadersInit两种形态从 packages/agents/src/agent-routing.ts 的类型定义可见cors: true自动启用一组默认 CORS 响应头cors: HeadersInit传入自定义响应头覆盖默认值适合需要指定具体来源、携带凭据的场景不传或false不添加任何 CORS 头跨域浏览器请求将失败。当传入true时默认解析出的响应头如下见 packages/agents/src/agent-routing.ts响应头值Access-Control-Allow-Origin*Access-Control-Allow-MethodsGET, POST, HEAD, OPTIONSAccess-Control-Allow-Headers*Access-Control-Max-Age86400同时底层路由逻辑会自动拦截OPTIONS预检请求并直接返回 CORS 头见 packages/agents/src/agent-routing.ts并在非 WebSocket 响应上统一附加这些头见 packages/agents/src/agent-routing.ts。也就是说开启cors: true后预检和实际响应两头都由框架代劳。自定义 CORS 头与预检处理示例并未满足于默认配置而是在 src/server.ts 中定义了更贴近生产的一组响应头const CORS_HEADERS { Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key, Access-Control-Allow-Credentials: true, Access-Control-Max-Age: 86400 };相比默认值这里额外声明了X-API-Key请求头与Access-Control-Allow-Credentials。随后在 Worker 的fetch入口中先手动处理OPTIONS预检请求再把其余请求交给routeAgentRequest见 src/server.tsexport default { async fetch(request: Request) { // 1. 处理 CORS 预检请求 if (request.method OPTIONS) { return new Response(null, { headers: CORS_HEADERS }); } // 2. 路由 Agent 请求并注入鉴权中间件 return ( (await routeAgentRequest(request, env, { cors: true, onBeforeConnect: async (request: Request) { console.log( onBeforeConnect called!); return authMiddleware(request); }, onBeforeRequest: async (request: Request) { console.log( onBeforeRequest called!); return authMiddleware(request); } })) || new Response(Not found, { status: 404 }) ); } };这里值得注意的实践组合是框架的cors: true负责兜底、自定义的OPTIONS分支负责精细化控制如允许凭据与自定义头两者同时启用并不冲突——手动预检返回后Agent 路由内的 CORS 逻辑自然不会再有OPTIONS进入。鉴权中间件WebSocket 与 HTTP 的统一拦截跨域之外示例还演示了如何在握手与请求两个阶段统一鉴权。authMiddleware从 URL 查询参数或Authorization请求头提取 token校验通过则原样返回request放行失败则返回 401 响应中断流程见 src/server.tsfunction authMiddleware(request: Request): Response | Request { const url new URL(request.url); // URL 参数可能进入应用日志切勿在日志中记录长期有效 token let token: string | null | undefined url.searchParams.get(token); if (!token) token request.headers.get(Authorization)?.substring(7); if (token) { console.log(Token found:, token); // 超级强的 token 校验演示用 if (token demo-token-123) { return request; // 放行继续请求流程 } } // 中断请求返回 401 console.log(Authentication failed); return new Response(Unauthorized: Invalid or missing authentication, { status: 401 }); }它通过routeAgentRequest的两个回调接入onBeforeConnect在WebSocket 握手建立之前执行决定是否允许客户端连接 AgentonBeforeRequest在HTTP 请求派发到 Agent 的onRequest之前执行决定是否允许请求进入。两个回调的返回契约一致返回Request表示放行返回Response表示中断。代码中Authorization的解析request.headers.get(Authorization)?.substring(7)正是提取Bearer token中Bearer之后的 token 部分。Agent 端到端逻辑鉴权通过后请求会被路由到MyAgentDurable Object其生命周期回调覆盖了连接的完整周期见 src/server.tsonConnect握手成功后读取 URL 查询参数中的token、userId向新连接发送欢迎消息onMessage收到客户端消息后回复带时间戳的回执并向其他所有连接广播Client id says: ...通过this.getConnections()遍历排除自己onClose客户端断开时打印日志onRequest处理 HTTP 请求返回已鉴权的处理结果文本。Worker 的 Durable Object 绑定在 wrangler.jsonc 中声明注意migrations使用的是new_sqlite_classesSQLite 支持的 Durable Object并启用了nodejs_compat兼容标志{ compatibility_date: 2026-06-11, compatibility_flags: [nodejs_compat], durable_objects: { bindings: [ { class_name: MyAgent, name: MyAgent } ] }, main: src/server.ts, migrations: [ { new_sqlite_classes: [MyAgent], tag: v1 } ], name: cross-domain }客户端useAgent 的两种跨域鉴权接入方式React 端通过agents/react提供的useAgenthook 连接 Worker页面 index.html 挂载 src/client.tsx。示例在同一个页面里提供了两种鉴权模式的切换通过顶部 checkbox并在 ReactSuspense中渲染加载鉴权数据期间展示 fallback。静态鉴权query 传参 Bearer 头StaticAuthApp使用对象形式的query把token与userId作为 WebSocket 握手 URL 的查询参数传给服务端对应服务端onConnect中从searchParams读取的值见 src/client.tsxconst agent useAgent({ agent: my-agent, host: http://localhost:8787, // 跨域指向 Worker query: { token: authToken, // 鉴权 tokendemo-token-123 userId: demo-user // 服务端校验用的用户标识 }, onMessage: (message) { /* 收到消息追加到消息列表 */ }, onError: (error) { console.error(WebSocket auth error:, error); } });UI 上还提供了输入框允许修改 token 并Update Token刷新连接。与此同时HTTP 通道使用fetch直接请求 Agent 的 REST 路径/agents/my-agent/default并把 token 放进Authorization: Bearer token头见 src/client.tsx——这正是服务端authMiddleware中Authorization头 → 取Bearer后缀那条解析路径的来源。异步鉴权async query 自动缓存生产场景中token 往往需要先从鉴权服务异步获取。AsyncAuthApp演示了把query写成异步函数的写法useAgent会自动检测并缓存该函数的返回结果连接会等到鉴权数据就绪后才发起见 src/client.tsx// 模拟鉴权服务并发获取 token 与用户信息 const asyncQuery useCallback(async () { console.log( Fetching authentication data...); const [token, user] await Promise.all([getAuthToken(), getCurrentUser()]); return { token, userId: user.id, timestamp: Date.now().toString() // 转为字符串以兼容 WebSocket 查询参数 }; }, []); const agent useAgent({ agent: my-agent, host: http://localhost:8787, query: asyncQuery, // 异步函数——自动检测并缓存 onMessage: (message) { /* ... */ }, onError: (error) { console.error(WebSocket error:, error); } });这种写法与useAgent的类型定义一致query既可以是静态的QueryObject也可以是返回PromiseQueryObject的函数见 packages/agents/src/react.tsx同时配套queryDeps异步查询缓存依赖与cacheTtl毫秒级缓存 TTL适合时间敏感的 token。UI 顶部的Suspensefallback Loading authentication...正是在异步查询期间展示的加载态。端到端效果与验证启动npm start后打开 Vite 提供的页面即可验证两条跨域链路WebSocket 链路在输入框发送消息 → 服务端onMessage触发客户端收到回执Server received ... at 时间若同时开两个浏览器标签还能看到广播消息Client id says: ...HTTP 链路点击 Send Authenticated HTTP Request →fetch携带Bearertoken 请求/agents/my-agent/default→ 服务端onBeforeRequest校验后进入onRequest客户端收到 Authenticated HTTP request processed ...响应文本。若去掉cors: true或不处理OPTIONS预检浏览器控制台将出现典型的 CORS 报错如Failed to fetch、WebSocket 握手被浏览器拦截。这也再次印证 README 的核心结论跨域场景下cors: true是routeAgentRequest的必选项而结合自定义 CORS 头、onBeforeConnect/onBeforeRequest鉴权中间件与useAgent的静态/异步query即可在 React 与 Worker Agent 分域部署时构建一条完整、安全的实时通信链路。进一步参考packages/agents/src/react.tsxuseAgent全部选项、packages/agents/src/agent-routing.tsrouteAgentRequest的 CORS 与路由实现以及 examples/agents-as-tools、examples/channels 等其他 Agent 接入示例。【免费下载链接】agentsBuild and deploy AI Agents on Cloudflare项目地址: https://gitcode.com/GitHub_Trending/agents1/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考