3. API Gateway构建RESTful API
API Gateway 是 AWS 无服务器架构中面向客户端的统一入口。它负责接收 HTTP 请求、执行鉴权与校验、把请求转发给后端(通常是 Lambda),再把结果按约定格式返回。要真正把 API 做“对”,需要同时理解三件事:选哪种 API 类型、如何定义资源与方法、以及如何用阶段和阶段变量管理多环境。
一、三种 API 类型怎么选
API Gateway 提供 REST、HTTP 和 WebSocket 三类 API,它们的定位差异明显:
- REST API:功能最全,支持 API Key、使用计划、请求验证、映射模板、缓存、WAF 集成、私有端点等。适合需要精细控制请求/响应转换、需要按用量计费或需要边缘优化的对外 API。
- HTTP API:更轻量、更低延迟、更便宜,原生支持 JWT 授权和 CORS 配置,但不支持映射模板、请求验证、API Key 与使用计划。适合纯代理到 Lambda 或 HTTP 后端的简单场景。
- WebSocket API:面向长连接双向通信,路由键由
$request.body.action或$connect/$disconnect决定,适合聊天、实时推送、协同编辑。
本节以 REST API 为主线,因为它覆盖了题目要求的全部能力。若只是把请求原样转给 Lambda,HTTP API 往往是更优选择。
二、资源与方法定义
REST API 的核心模型是“资源树 + 方法”。资源对应 URL 路径,方法对应 HTTP 动词。例如要暴露一个订单查询接口,可以定义:
/orders GET 列出订单
/orders POST 创建订单
/orders/{orderId} GET 查询单个订单
/orders/{orderId} DELETE 删除订单
其中 {orderId} 是路径参数,API Gateway 会把它放进 event.pathParameters.orderId 传给 Lambda。方法上还可以配置请求参数校验:把 orderId 标记为必填,并限制为数字或 UUID 正则,这样非法请求在进入 Lambda 之前就被拒绝,既省成本又减少后端防御代码。
三、阶段、部署与阶段变量
REST API 的变更不会自动生效,必须“部署”到一个阶段(Stage)。阶段是 API 的一个快照加一组配置,常见做法是建 dev、test、prod 三个阶段,各自指向不同的 Lambda 别名或不同的后端地址。
阶段变量(Stage Variables)是阶段级别的键值对,可以在集成请求的 URI、Lambda 函数名、映射模板中通过 ${stageVariables.xxx} 引用。典型用法是让同一个 API 定义在不同阶段指向不同后端:
阶段 dev : stageVariables.lambdaAlias = dev
阶段 prod : stageVariables.lambdaAlias = prod
集成 URI:
arn:aws:apigateway:cn-north-1:lambda:path/2015-03-31/functions/
arn:aws:lambda:cn-north-1:123456789012:function:orderService:${stageVariables.lambdaAlias}/invocations
这样切换环境只需改阶段变量,而不必复制整套 API。注意:使用阶段变量指向 Lambda 别名时,需要在 Lambda 上添加权限,允许 API Gateway 以该别名调用,否则会返回 500。
四、请求验证与映射模板
请求验证器(Request Validator)可以校验请求体是否符合模型(Model)、参数是否满足约束。开启后,不符合的请求直接返回 400,不会触发 Lambda。
映射模板(Mapping Template)使用 VTL(Velocity Template Language)在请求进入后端前重塑数据,或在响应返回客户端前重塑结果。例如把客户端传来的扁平 JSON 包装成 Lambda 期望的结构:
#set($inputRoot = $input.path('$'))
{
"orderId": "$inputRoot.orderId",
"source": "api-gateway",
"stage": "$context.stage"
}
映射模板也常用于把 Lambda 返回的 JSON 转成纯文本、XML 或自定义错误结构。若不需要转换,选择“透传(proxy integration)”即可,此时 Lambda 必须返回 statusCode、headers、body 三要素。
五、与 Lambda 集成与 CORS
Lambda 集成分两种:Lambda 代理集成(Lambda Proxy)把整个请求原样交给 Lambda,由 Lambda 决定状态码和响应体,配置最简单;Lambda 自定义集成则配合映射模板做请求/响应转换,控制更细但配置更多。多数 REST API 场景推荐代理集成。
浏览器跨域调用时,需要配置 CORS。REST API 的 CORS 不是自动的,需要为每个资源添加 OPTIONS 方法,返回如下响应头:
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET,POST,DELETE,OPTIONS
Access-Control-Allow-Headers: Content-Type,Authorization
如果使用代理集成,也可以在 Lambda 中统一返回这些头,但 OPTIONS 预检请求仍需 API Gateway 直接响应,否则预检会打到 Lambda 造成额外调用。
六、一个可复用的配置检查清单
把上面的要点整理成一份可直接对照的检查表,便于在创建或评审 REST API 时逐项确认:
| 检查项 | 推荐做法 | 判断依据 |
|---|---|---|
| API 类型 | 需要映射模板/请求验证/API Key 选 REST;纯代理选 HTTP | 功能需求清单 |
| 资源与方法 | 路径参数用 {param},方法按语义选动词 | URL 可读性与 REST 规范 |
| 阶段 | 至少 dev/prod 两阶段,各自独立部署 | 环境隔离要求 |
| 阶段变量 | 用 ${stageVariables.lambdaAlias} 指向别名 | 切换环境不改 API 定义 |
| 请求验证 | 对必填参数和请求体模型开启验证器 | 非法请求返回 400 而非 500 |
| 映射模板 | 仅在需要转换时使用,否则用代理集成 | 后端期望的数据结构 |
| CORS | 为每个资源添加 OPTIONS 方法并返回允许头 | 浏览器预检通过 |
aws lambda add-permission 授权 API Gateway 调用该别名,否则集成会返回 500。这是最常见的“配置看起来对但调用失败”的原因。掌握以上内容后,就可以用一套 API 定义覆盖多环境,并在网关层完成校验与转换,让 Lambda 专注于业务逻辑。实际落地时建议先用代理集成跑通链路,再按需引入映射模板和请求验证,避免一开始就陷入 VTL 的复杂度。