🎯 CORS 是什么?
CORS 是一种安全机制,允许网页从不同的域(域名、协议、端口)请求资源。由于您的前端和后端部署在不同的域名上:
- 前端:
https://your-pages.pages.dev
(Cloudflare Pages) - 后端:
https://your-worker.workers.dev
(Cloudflare Workers)
浏览器会阻止这种跨域请求,除非后端明确允许。
🔍 代码逐行分析
typescript
export function handleCors(request: Request): Response | null {
// 检查是否是 OPTIONS 请求(预检请求)
if (request.method === 'OPTIONS') {
// 如果是预检请求,返回一个空的响应和CORS头
return new Response(null, {
headers: {
// 允许指定的前端域名进行跨域访问
'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
// 允许的HTTP方法
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
// 允许的请求头
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
});
}
// 如果不是OPTIONS请求,返回null,让主流程继续处理
return null;
}
🌐 CORS 工作原理
1. 预检请求 (OPTIONS)
当浏览器发送跨域请求时,会先发送一个 OPTIONS
请求来询问服务器是否允许实际请求。
示例流程:
前端 (https://your-pages.pages.dev)
→ 发送 OPTIONS 预检请求到后端
← 后端返回 CORS 头
→ 浏览器检查通过后发送实际请求 (GET/POST)
← 后端返回实际数据
2. 实际请求
预检通过后,浏览器才会发送真正的请求(GET、POST等)。
🛠️ 改进建议
1. 动态允许域名(推荐)
typescript
export function handleCors(request: Request): Response | null {
// 允许的前端域名列表
const allowedOrigins = [
'https://your-pages.pages.dev', // 生产环境
'http://localhost:3000', // 本地开发
'http://localhost:5173' // Vite 开发服务器
];
const origin = request.headers.get('Origin');
const allowedOrigin = allowedOrigins.includes(origin || '') ? origin : allowedOrigins[0];
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': allowedOrigin || '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-Requested-With',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': '86400', // 24小时缓存
},
});
}
return null;
}
2. 在实际响应中也添加CORS头
typescript
// 在您的各个handler中,也需要添加CORS头
export function successResponse(data: any, message?: string): Response {
return new Response(JSON.stringify({ success: true, data, message }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
'Access-Control-Allow-Credentials': 'true',
},
});
}
export function errorResponse(message: string, status: number = 500): Response {
return new Response(JSON.stringify({ success: false, error: message }), {
status,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'https://your-pages.pages.dev',
'Access-Control-Allow-Credentials': 'true',
},
});
}
3. 完整的使用示例
typescript
// src/index.ts
import { handleCors, successResponse } from './utils/response';
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
// 1. 首先处理CORS预检请求
const corsResponse = handleCors(request);
if (corsResponse) return corsResponse;
// 2. 处理实际请求
const url = new URL(request.url);
if (url.pathname === '/api/test') {
// 3. 在实际响应中也添加CORS头
return successResponse({ message: 'Hello World' });
}
return new Response('Not found', { status: 404 });
}
};
🔧 常见CORS头说明
头字段 | 说明 | 示例 |
---|---|---|
Access-Control-Allow-Origin |
允许的源 | https://your-site.com |
Access-Control-Allow-Methods |
允许的HTTP方法 | GET, POST, OPTIONS |
Access-Control-Allow-Headers |
允许的请求头 | Content-Type, Authorization |
Access-Control-Allow-Credentials |
是否允许发送cookie | true |
Access-Control-Max-Age |
预检请求缓存时间 | 86400 (秒) |
💡 重要提示
-
** credentials **:如果前端需要发送cookie,需要设置
Access-Control-Allow-Credentials: true
,并且Access-Control-Allow-Origin
不能是通配符*
-
** 生产环境配置 **:记得将
https://your-pages.pages.dev
替换为您实际的前端域名 -
** 本地开发 **:建议允许本地开发服务器的域名,方便调试
这段代码是确保您的前后端分离架构能够正常工作的关键!🚀