CORS与API网关生存指南 - 无服务器架构

作者:API传播员 · 2025-12-27 · 阅读时间:5分钟

无服务器架构中最受欢迎的应用场景之一。通过无服务器架构,您可以构建一个简单且可扩展的后端,同时避免繁重的运维工作。然而,在实现过程中,CORS(跨域资源共享)问题可能会成为一个常见的挑战。


快速指南:如何解决无服务器架构中的 CORS 问题

如果您想快速解决无服务器应用中的 CORS 问题,可以按照以下步骤操作:

  1. 返回 CORS 标头

    在响应中添加以下关键 CORS 标头:

    • Access-Control-Allow-Origin
    • Access-Control-Allow-Credentials

    示例代码如下:

   module.exports.getProduct = (event, context, callback) => {
       const product = retrieveProduct(event);
       const response = {
           statusCode: 200,
           headers: {
               'Access-Control-Allow-Origin': '*',
               'Access-Control-Allow-Credentials': true,
           },
           body: JSON.stringify({ product: product }),
       };
       callback(null, response);
   };

   module.exports.createProduct = (event, context, callback) => {
       const product = createProduct(event);
       const response = {
           statusCode: 200,
           headers: {
               'Access-Control-Allow-Origin': '*',
               'Access-Control-Allow-Credentials': true,
           },
           body: JSON.stringify({ product: product }),
       };
       callback(null, response);
   };
  1. 配置自定义授权器

    如果您使用了自定义授权器,需要在 serverless.yml 文件的 resources 块中添加以下 CloudFormation 配置:

    Resources:
     GatewayResponseDefault4XX:
       Type: "AWS::ApiGateway::GatewayResponse"
       Properties:
         ResponseParameters:
           gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
           gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
         ResponseType: DEFAULT_4XX
         RestApiId:
           Ref: 'ApiGatewayRestApi'

理解 CORS 飞行前请求

什么是飞行前请求?

当浏览器发起非“简单请求”时,会先发送一个 OPTIONS 方法的飞行前请求,以确认目标资源是否支持跨域请求。目标资源会返回允许的 HTTP 方法和标头等信息。

浏览器何时发送飞行前请求?

以下情况会触发飞行前请求:

  • 使用 PUTDELETE 方法。
  • Content-Type 标头不属于以下类型之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • 请求包含自定义标头(如身份验证标头)。

如何处理飞行前请求?

在无服务器架构中,您可以通过在 API 网关的端点中配置 OPTIONS 方法来处理飞行前请求。在 serverless.yml 文件中,添加以下配置:

functions:
  yourFunction:
    handler: handler.yourFunction
    events:
      - http:
          path: your-path
          method: get
          cors: true

此配置将自动为 API 网关启用 CORS 支持,并允许所有域访问。如果需要更高级的自定义,可以指定允许的域和标头。


使用无服务器框架处理 CORS

在无服务器框架中,您需要确保每个跨域请求的响应中都包含以下标头:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Credentials(如果使用了 Cookie 或其他身份验证)

以下是一个示例代码片段,展示如何在 handler.js 文件中添加这些标头:

const response = {
    statusCode: 200,
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': true,
    },
    body: JSON.stringify({ message: 'Success' }),
};

如果您的函数包含多个逻辑路径,手动添加这些标头可能会变得繁琐。幸运的是,有一些工具可以简化这一过程,例如 Middy 中间件库。


带有自定义授权器的 CORS 配置

当自定义授权器拒绝请求时,默认情况下不会返回 CORS 标头,这可能导致客户端浏览器无法正确解析响应。为了解决这一问题,您可以在 API 网关中添加自定义 GatewayResponse:

Resources:
  GatewayResponseUnauthorized:
    Type: "AWS::ApiGateway::GatewayResponse"
    Properties:
      ResponseParameters:
        gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
      ResponseType: UNAUTHORIZED
      RestApiId:
        Ref: 'ApiGatewayRestApi'

CORS 与 Cookie 凭据

如果您的应用需要支持 Cookie 凭据,可以通过以下两种方式实现:

  1. 固定来源

    如果只有一个固定的来源,可以直接在 Lambda 函数的响应中硬编码允许的来源:

    headers: {
       'Access-Control-Allow-Origin': 'https://example.com',
       'Access-Control-Allow-Credentials': true,
    }
  2. 动态来源

    如果有多个来源,可以动态检查请求头中的 Origin,并根据允许的来源列表返回相应的标头:

   const allowedOrigins = ['https://example1.com', 'https://example2.com'];
   const origin = event.headers.origin;

   const response = {
       statusCode: 200,
       headers: {
           'Access-Control-Allow-Origin': allowedOrigins.includes(origin) ? origin : 'null',
           'Access-Control-Allow-Credentials': true,
       },
       body: JSON.stringify({ message: 'Success' }),
   };

总结

CORS 问题虽然复杂,但通过正确的配置和工具支持,可以大大简化处理过程。在无服务器架构中,您可以通过以下步骤高效地解决 CORS 问题:

  • 在响应中添加必要的 CORS 标头。
  • 配置 API 网关的 OPTIONS 方法以处理飞行前请求。
  • 使用工具库(如 Middy)简化标头管理。
  • 针对自定义授权器和 Cookie 凭据采取额外的配置措施。

通过这些方法,您可以轻松应对无服务器架构中的 CORS 挑战。

原文链接: https://www.serverless.com/blog/cors-api-gateway-survival-guide