首页
/ 使用 Serverless Framework 为 AWS Lambda 配置 HTTP API(API Gateway v2)事件:从 CORS、鉴权到自定义域名

使用 Serverless Framework 为 AWS Lambda 配置 HTTP API(API Gateway v2)事件:从 CORS、鉴权到自定义域名

2026-09-08 16:14:45作者:卓艾滢Kingsley

本指南以 docs/sf/providers/aws/events/http-api.md 为骨架,系统讲解如何在 Serverless Framework 中通过 httpApi 事件把 AWS Lambda 函数暴露为 API Gateway v2(HTTP API)端点。你将掌握事件定义与参数语法、CORS 精细配置、JWT / Lambda(请求) / AWS IAM 三类授权器、访问日志、多服务复用 API、payload 版本选择以及自定义域名接入的完整步骤,并结合仓库中 packages/serverless/lib/plugins/aws/package/compile/events/http-api.js 的编译实现理解背后的 CloudFormation 生成逻辑。

背景:API Gateway v1 与 v2 的选择

API Gateway 提供两个版本部署 HTTP API:

  • v1(REST API):功能最全的传统版本;
  • v2(HTTP API):部署更快、运行成本更低,是新增服务时的推荐选择。

需要注意命名容易混淆:两个版本都支持部署任意类型的 HTTP API(REST、GraphQL 等)。本文档只讨论 v2 HTTP API,对应 httpApi 事件;若你希望使用 v1 REST API,请参考 API Gateway(REST API)事件指南

在仓库源码中,httpApi 事件由 http-api.js 编译插件 实现,其 package:compileEvents 钩子依次执行 compileApi()compileLogGroup()compileStage()compileAuthorizers()compileEndpoints() 五个步骤(http-api.js 第 67-77 行),最终把配置翻译成 AWS::ApiGatewayV2::* 系列 CloudFormation 资源。

事件定义基础

httpApi 事件同时支持字符串缩写对象完整写法两种形式:

functions:
  simple:
    handler: handler.simple
    events:
      - httpApi: 'PATCH /elo'
  extended:
    handler: handler.extended
    events:
      - httpApi:
          method: POST
          path: /post/just/to/this/path

simple 使用 'PATCH /elo'methodpath 写在一行;extended 显式拆分两个字段,语义完全等价。

从源码可以印证事件命名的严格性:编译插件中定义了合法方法集合 ANY / GET / POST / PUT / PATCH / OPTIONS / HEAD / DELETE,并通过两条正则分别校验「单方法缩写」和「方法 + 路径」两种字符串写法,不匹配即报配置错误(http-api.js 第 9-26 行)。

Catch-alls 通配

支持用 * 通配整个 API 或单个方法:

functions:
  catchAllAny:
    handler: index.catchAllAny
    events:
      - httpApi: '*'
  catchAllMethod:
    handler: handler.catchAllMethod
    events:
      - httpApi:
          method: '*'
          path: /any/method
  • httpApi: '*':捕获所有路径与所有方法(对应默认路由);
  • method: '*' + 指定 path:只对该路径开放所有方法。

路径参数

HTTP API 路由天然支持 {param} 占位符,与 Lambda Proxy 集成一起使用时,参数值会出现在传给函数的事件对象中:

functions:
  params:
    handler: handler.params
    events:
      - httpApi:
          method: GET
          path: /get/for/any/{param}

端点超时与函数超时的关系

HTTP API 使用 API Gateway 的默认与最大超时 30 秒。因此务必将函数超时控制在 29 秒以内,否则会出现 Lambda 实际调用成功、但客户端收到 503 状态码的现象——这正是 API Gateway 在 30 秒处主动截断等待的典型表现。

CORS 配置

HTTP API 允许在 provider.httpApi.cors 下配置对所有已配置端点全局生效的 CORS 响应头。

一键开启默认配置

provider:
  httpApi:
    cors: true

默认会输出如下请求头(该默认值在源码中硬编码于 http-api.js 第 34-45 行):

Header Value
Access-Control-Allow-Origin *
Access-Control-Allow-Headers Content-Type, X-Amz-Date, Authorization, X-Api-Key, X-Amz-Security-Token, X-Amz-User-Agent, X-Amzn-Trace-Id
Access-Control-Allow-Methods OPTIONS, (...all defined in endpoints)

精细自定义

如需微调,可逐项配置:

provider:
  httpApi:
    cors:
      allowedOrigins:
        - https://url1.com
        - https://url2.com
      allowedHeaders:
        - Content-Type
        - Authorization
      allowedMethods:
        - GET
      allowCredentials: true
      exposedResponseHeaders:
        - Special-Response-Header
      maxAge: 6000 # In seconds

源码层面,compileApi() 会把上述字段映射为 AWS::ApiGatewayV2::ApiCorsConfigurationAllowCredentialsAllowHeadersAllowMethodsAllowOriginsExposeHeadersMaxAge),并在未配置 cors 时不生成该块(http-api.js 第 170-182 行)。

JWT Authorizers(JWT 授权器)

JWT 授权器是限制 HTTP API 端点访问的方式之一。要让 serverless.yml 中配置的端点启用鉴权,分两步:

1. 在 provider.httpApi.authorizers 定义授权器

provider:
  httpApi:
    authorizers:
      someJwtAuthorizer:
        type: jwt
        identitySource: $request.header.Authorization
        issuerUrl: https://cognito-idp.${region}.amazonaws.com/${cognitoPoolId}
        audience:
          - ${client1Id}
          - ${client2Id}

典型场景是把 Amazon Cognito 用户池作为签发方:issuerUrl 指向用户池的签发地址,audience 列出允许的应用客户端 ID,identitySource 声明从请求头 Authorization 读取令牌。

2. 在端点级引用授权器并声明 OAuth scopes

functions:
  someFunction:
    handler: index.handler
    events:
      - httpApi:
          method: POST
          path: /some-post
          authorizer:
            name: someJwtAuthorizer
            scopes: # Optional
              - user.id
              - user.email

name 关联到 provider 级定义的授权器;scopes 可选,用于限定该路由所需 OAuth 作用域。编译插件在 compileAuthorizers() 中为每个授权器生成 AWS::ApiGatewayV2::Authorizer 资源(类型为 JWTREQUEST),并将 identitySource 规范化为数组后写入(http-api.js 第 266-285 行)。

Lambda(Request)Authorizers(请求授权器)

除 JWT 外,还可以用自定义 Lambda 函数充当授权器。此类授权器 type 固定为 request,其来源函数既可以来自当前服务,也可以来自服务之外。

使用本服务内的函数作为授权器

需先在 provider 级按函数名引用授权器,再在端点中引用它:

provider:
  name: aws
  httpApi:
    authorizers:
      customAuthorizer:
        type: request
        functionName: authorizerFunc

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: get
          path: /hello
          authorizer:
            name: customAuthorizer

  authorizerFunc:
    handler: authorizer.handler

使用服务外部的函数作为授权器

若授权函数属于其他部署,直接传其 ARN:

provider:
  name: aws
  httpApi:
    authorizers:
      customAuthorizer:
        type: request
        functionArn: arn:aws:lambda:us-east-1:11111111111:function:external-authorizer

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: get
          path: /hello
          authorizer:
            name: customAuthorizer

授权器完整配置项

  • type:自定义 Lambda 授权器必须设为 request
  • name:可选,自定义授权器名称。
  • functionName:本服务内作为授权器使用的函数名;与 functionArn 互斥。
  • functionArn:授权函数的 ARN,支持 CloudFormation 内建函数(如 Fn::ImportValue);与 functionName 互斥。
  • resultTtlInSeconds:可选,授权结果缓存 TTL,取值 0(不缓存)到 3600(1 小时)。设为非 0 时必须同时定义 identitySource(它同时充当授权结果缓存的键)。
  • enableSimpleResponses:可选,是否让授权函数以「简单格式」返回授权响应,默认 false
  • payloadVersion:可选,发送给授权函数的 payload 版本,默认 '2.0'
  • identitySource:可选,一个或多个请求参数映射表达式(如 $request.header.Auth),授权器会校验其非空;当 resultTtlInSeconds 非 0 时为必填。
  • managedExternally:可选,标记授权函数是否完全由外部管理(例如位于其他 AWS 账户)。设为 true 时会跳过为该授权函数创建 Lambda 权限资源。

完整配置示例:

provider:
  name: aws
  httpApi:
    authorizers:
      customAuthorizer:
        type: request
        functionName: authorizerFunc # Mutually exclusive with `functionArn`
        functionArn: arn:aws:lambda:us-east-1:11111111111:function:external-authorizer # Mutually exclusive with `functionName`
        name: customAuthorizerName
        resultTtlInSeconds: 300
        enableSimpleResponses: true
        payloadVersion: '2.0'
        identitySource:
          - $request.header.Auth
          - $request.header.Authorization
        managedExternally: true # 仅当使用外部函数时适用,用于阻止创建权限资源

注意 functionNamefunctionArn 两个字段虽然同框出现,但语义上互斥,实际配置二选一即可。

AWS IAM 授权

也可以借助 AWS IAM 策略来保护 HTTP API 端点:把事件上的 authorizer 设为 type: aws_iam 即可。此后只有具备调用该 API 权限的 IAM 身份(如使用 SigV4 签名)才能访问:

provider:
  name: aws

functions:
  hello:
    handler: handler.hello
    events:
      - httpApi:
          method: get
          path: /hello
          authorizer:
            type: aws_iam

Access logs(访问日志)

注意: 如果完全没有设置 logs.httpApi,HTTP API 日志将保持关闭。

在 provider 中开启后即可启用部署阶段的访问日志:

provider:
  logs:
    httpApi: true

默认日志格式为:

{
  "requestId": "$context.requestId",
  "ip": "$context.identity.sourceIp",
  "requestTime": "$context.requestTime",
  "httpMethod": "$context.httpMethod",
  "routeKey": "$context.routeKey",
  "status": "$context.status",
  "protocol": "$context.protocol",
  "responseLength": "$context.responseLength"
}

可借助 format 覆盖为自定义格式(支持 $context.* 变量组合):

provider:
  logs:
    httpApi:
      format: '{ "ip": "$context.identity.sourceIp", "requestTime":"$context.requestTime" }'

日志变量详情参见 AWS 官方「HTTP API 日志变量」文档。实现层面,compileLogGroup() 会为访问日志创建 AWS::Logs::LogGroup(并继承 provider 的日志保留天数与数据保护策略设置,http-api.js 第 188-211 行);compileStage() 中则将格式与日志组 ARN 写入 AWS::ApiGatewayV2::StageAccessLogSettingshttp-api.js 第 233-244 行)。

在多个服务间复用 HTTP API

可以将当前服务配置的端点挂载到外部创建的 HTTP API,只需在 provider 提供 API id:

provider:
  httpApi:
    id: xxxx # id of externally created HTTP API to which endpoints should be attached.

由于 id 本身可能是由其他 CloudFormation 栈导出后由 Fn::ImportValue 引用得到:

provider:
  httpApi:
    id:
      Fn::ImportValue: xxxx # 代表外部 HTTP API id 的导出值名称

约束:使用外部 HTTP API 时,不再创建 API 与 Stage 资源,因此不支持扩展 CORS、访问日志或授权器等依赖 API/Stage 的配置。源码中 compileApi()compileStage() 遇到 this.config.id 都会提前返回(http-api.js 第 157 行第 213 行)。

HTTP API URL

部署带 httpApi 事件的函数后,serverless deployserverless info 的输出中会展示 HTTP API 的 URL。该 URL 同时以 HttpApiUrl 输出的形式导出为 CloudFormation Output——compileStage() 通过 Ref API id 拼出形如 https://{apiId}.execute-api.{region}.{suffix} 的地址并写入 HttpApiIdHttpApiUrl 两个输出(http-api.js 第 245-264 行)。你可以在其它栈中 Fn::ImportValue 这个导出值使用。

共享 Authorizer(针对外部 HTTP API)

对于复用的外部 HTTP API,可以类似 REST API 那样使用共享授权器:先引用其 authorizerId(可硬编码或用 Ref 指向自定义创建的 AWS::ApiGatewayV2::Authorizer 资源),并在事件上声明授权器 type 与可选 scopes

httpApi:
    id: xxxx # Required

functions:
  createUser:
     ...
    events:
      - httpApi:
          path: /users
          ...
          authorizer:
            # Type of referenced authorizer
            type: jwt
            # Provide authorizerId
            id:
              Ref: ApiGatewayAuthorizer  # or hard-code Authorizer ID
            scopes: # Optional - List of Oauth2 scopes
              - myapp/myscope

  deleteUser:
     ...
    events:
      - httpApi:
          path: /users/{userId}
          ...
          authorizer:
            # Type of referenced authorizer
            type: jwt
            # Provide authorizerId
            id:
              Ref: ApiGatewayAuthorizer  # or hard-code Authorizer ID
            scopes: # Optional - List of Oauth2 scopes
              - myapp/anotherscope

resources:
  Resources:
    ApiGatewayAuthorizer:
      Type: AWS::ApiGatewayV2::Authorizer
      Properties:
        ApiId:
          Ref: YourApiGatewayName
        AuthorizerType: JWT
        IdentitySource:
          - $request.header.Authorization
        JwtConfiguration:
          Audience:
            - Ref: YourCognitoUserPoolClientName
          Issuer:
            Fn::Join:
              - ""
              - - "https://cognito-idp."
                - "${opt:region, self:provider.region}"
                - ".amazonaws.com/"
                - Ref: YourCognitoUserPoolName

当使用共享的 Lambda 自定义授权器时,把 type 设为 request 即可;scopes 仅在 JWT 场景使用。

Event / Payload 格式(1.0 与 2.0)

HTTP API 只提供 Lambda 的 proxy 集成选项——事件对象中携带请求头、查询字符串等完整 HTTP 上下文。该事件存在 1.02.0 两种格式,默认 2.0,可通过 payload 降级为 1.0。可在 provider 层全局配置:

provider:
  httpApi:
    payload: '1.0'

也可在函数级通过 httpApi.payload 单独指定,优先级高于 provider 层配置:

functions:
  hello:
    handler: index.handler
    httpApi:
      payload: '1.0'
    events:
      - httpApi:
          path: /hello
          method: GET

源码按「函数级优先于 provider 级、都没有则回落默认 '2.0'」的顺序解析版本(http-api.js 第 736 行),随后通过 Lambda 目标 ARN 与 resolveLambdaTarget() 关联到函数。

Detailed Metrics(详细指标)

开启后即可在 CloudWatch 中对 HTTP API 建立监控与告警:

provider:
  httpApi:
    metrics: true

该开关会落到 Stage 的 DefaultRouteSettings.DetailedMetricsEnabledhttp-api.js 第 218-220 行)。

Tags 标签

设置 provider.httpApi.useProviderTags: true 后,provider.tags 定义的所有标签都会应用到 API Gateway 及其 Stage:

provider:
  tags:
    project: myProject
  httpApi:
    useProviderTags: true

上例中 project: myProject 会被同时打到 API Gateway 与 API Gateway Stage。注意:如果 API Gateway 上存在由 Serverless Framework 之外的途径添加的旧标签,这些标签会在部署时被清除。另请注意,当前仓库的实现中 useProviderTags 已被标记为「不再生效」——provider 标签默认就会应用于 HTTP API,配置里可以安全移除该属性并关注框架的弃用告警(http-api.js 第 56-65 行)。

禁用默认端点

默认情况下,客户端可用 https://{api_id}.execute-api.{region}.amazonaws.com 端点调用 API。若要求客户端必须通过自定义域名访问,可禁用默认端点:

provider:
  httpApi:
    disableDefaultEndpoint: true

该配置在 compileApi() 中映射为 AWS::ApiGatewayV2::ApiDisableExecuteApiEndpoint 属性(http-api.js 第 161-164 行)。

服务命名(Naming)

默认情况下 HTTP API 名称为 ${stage}-${service};如需调整可以启用:

provider:
  httpApi:
    shouldStartNameWithService: true

启用后命名顺序变为 ${service}-${stage},便于资源按服务名聚合管理。

自定义域名接入

API Gateway 为 HTTP API 生成的 URL 形如:

https://<random>.execute-api.<region>.amazonaws.com/

可以通过以下三步替换为自有域名:

Step 1:在 AWS ACM 创建 HTTPS 证书

  • 打开 AWS Certificate Manager(ACM);
  • 切换到应用所在区域;
  • 点击 "Request a certificate",选择 "Request a public certificate" 继续;
  • 填入域名后继续;
  • 选择域名校验方式:
    • 邮箱校验(Email validation):需点击发送至 admin@your-domain.com 邮件中的链接;
    • DNS 校验(Domain validation):需在 DNS 配置中新增 CNAME 记录;
  • 完成上述任一校验。

Step 2:在 API Gateway 配置自定义域名

  • 打开 API Gateway 的 "Custom Domain"(域名)管理页面;
  • 切换到应用所在区域;
  • 点击 "Create";
  • 输入域名并选择上一步创建的证书,确认信息;
  • 域名创建完成后,进入 "API mappings" 页签;
  • 点击 "Configure API mappings" → "Add new mapping";
  • 选择你的 HTTP API 与 $default Stage;
  • 点击 "Save"。

Step 3:配置域名的 DNS

  • 若使用 Route53:
    • 打开对应的 Hosted Zone;
    • 点击 "Create record";
    • "Record type" 选 "A";
    • "Route traffic to" 选择 "Alias",再选中你的 API Gateway;
    • 完成记录创建。
  • 若使用其他域名注册商:
    • 打开自定义域名名称下的 "Configurations" 页签;
    • 记录 "API Gateway domain name"(形如 d-1234567890.execute-api.us-east-1.amazonaws.com);
    • 创建一条 CNAME 记录,把自有域名指向该 API Gateway 域名。

自定义域名配置完成后,即可按上文「禁用默认端点」一节强制走自定义域名:

provider:
  httpApi:
    disableDefaultEndpoint: true

小结

httpApi 事件把「声明式路由配置 → CloudFormation 资源」的转换封装在 编译插件 内部,覆盖 API、Stage、日志组、授权器与路由的全部编排,并配套了完整的单元测试(见 http-api.test.js 测试)。从简单的 'PATCH /elo' 缩写、Catch-all 通配与路径参数,到 CORS、三类授权器、访问日志、payload 版本、指标、标签、共享 API 与自定义域名,以上配置均可在单个 serverless.yml 中完成,适合直接作为生产环境的部署参照。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.81 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
920
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.79 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
390