如何在 Pages Functions 上启用 CORS?

Benjamin CarterBenjamin Carter
8 分钟阅读
Spt 8, 2025

跨域资源共享(CORS)是浏览器实现的一种安全机制,用于控制 Web 应用程序如何与不同源的资源交互。默认情况下,同源策略限制 Web 页面向其他域的服务器发起请求。CORS 通过允许服务器使用 HTTP 响应头来指定哪些源可以访问其资源,从而有选择地放宽这一限制。

关键 CORS 响应头及其功能

  • Access-Control-Allow-Origin: 指定允许访问资源的源。使用 * 允许所有源(不建议用于敏感数据);指定特定源(例如,https://app.example)可以提高安全性。
  • Access-Control-Allow-Methods: 列出访问资源时允许的 HTTP 方法(例如,GET,POST,PUT,PATCH,DELETE,OPTIONS)。
  • 指定可以包含在实际请求中的自定义头(例如,Authorization,Content-Type,X-CSRF-Token)。
  • Access-Control-Allow-Credentials: 指示是否允许凭证(例如,cookies 或 HTTP 身份验证)。必须设置为 true,并且只能与显式(非 * )源一起使用。
  • Access-Control-Max-Age: 定义预检请求的结果可以由浏览器缓存的时间(以秒为单位)(例如,86400 表示 24 小时)。

当请求被视为“非简单请求”(例如使用自定义头或其他方法而非 GET/POST)时,浏览器会自动向服务器发送预检 OPTIONS 请求。服务器必须返回适当的 CORS 头;否则,浏览器将阻止实际请求。

通过 Pages Functions 解决跨源问题

Pages Functions 提供了一个无服务器代码执行环境,运行在 EdgeOne 边缘节点上。开发者只需编写业务逻辑并配置触发规则——无需管理服务器基础设施。代码在靠近终端的边缘节点上弹性安全地执行。

通过 headers API 解决 CORS

典型代码示例:

// functions/api/hello.ts
export async function onRequest({ request }) {
  const origin = request.headers.get("Origin");
  // 业务逻辑或代理上游请求
  const response = await fetch(request);

  // 设置CORS响应头
  response.headers.set("Access-Control-Allow-Origin", origin || "*");
  response.headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
  response.headers.set("Access-Control-Max-Age", "86400");

  return response;
}

注意:如果需要支持凭证(例如 cookies),必须将 Access-Control-Allow-Origin 设置为特定域,并添加 true

基于地理位置的 CORS

您还可以使用 EdgeOne 的地理位置信息实施区域特定的 CORS 策略:

// functions/api/hello.ts
export async function onRequest({ request }) {
  const origin = request.headers.get("Origin");
  const country = (request.eo.geo && request.eo.geo.country) || "US";

  const corsMap = {
    US: { origins: ["https://us.example.com"], credentials: true },
    CA: { origins: ["https://ca.example.com"], credentials: true },
    EU: { origins: ["https://eu.example.com"], credentials: true },
  };
  const region = corsMap[country] || { origins: ["https://global.example.com"], credentials: false };
  const isAllowed = origin && region.origins.includes(origin);

  const headers = {
    "Access-Control-Allow-Origin": isAllowed ? origin : "null",
    "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type, Authorization",
    "Access-Control-Allow-Credentials": region.credentials.toString(),
    "Access-Control-Max-Age": "86400",
  };

  if (request.method === "OPTIONS") {
    return new Response(null, { status: 204, headers });
  }

  return new Response(JSON.stringify({ country }), {
    headers: { ...headers, "content-type": "application/json; charset=UTF-8" },
  });
}

测试您的设置

# 预检
curl -i -X OPTIONS https://your-domain.edgeone.app/api/hello \
  -H "Origin: https://app.example" \
  -H "Access-Control-Request-Method: POST"

# 简单请求
curl -i https://your-domain.edgeone/api/hello \
  -H "Origin: https://app.example"

查看200 状态的 OPTIONS 调用和两个响应中的正确 CORS 头。

常见 CORS 场景和解决方案

  • 从本地前端开发调用 API 时的 CORS 错误:API 服务器必须包含允许本地开发域的 CORS 头。
  • 第三方应用集成您的 API:动态确定 Origin 并根据需要返回相应的 CORS 头以增强安全性。
  • 支持凭证的跨源请求Access-Control-Allow-Credentials 必须设置为 true,并且 Access-Control-Allow-Origin 不能为 *

总结

CORS 是在前端/后端分离和微服务架构中不可避免的问题。通过灵活地在 EdgeOne Pages Functions 中设置 CORS 响应头,您可以有效且安全地满足跨源访问要求。对于更复杂的场景,您可以利用环境变量、KV 存储和其他功能来实现动态授权和个性化的跨源策略。

有关高级用法,请参阅 Pages Functions 文档