如何在CDK中让HTTP API Gateway按端点拒绝格式错误的JSON?
解决方案:基于Lambda+TypeScript实现API Gateway请求参数校验
核心说明
TypeScript的Interface仅为编译时类型提示,运行时会被完全擦除,无法直接用于参数校验。需结合运行时校验逻辑,再通过Lambda返回对应状态码,让API Gateway透传给请求方。
具体实现步骤
1. 选择运行时校验方案
推荐使用轻量且TS友好的zod库,或手动编写校验函数,以下是zod的示例:
import { z } from "zod"; import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda"; // 定义参数校验规则(替代Interface的运行时校验) const ExampleRequestSchema = z.object({ username: z.string().min(1, "用户名不能为空"), age: z.number().int().positive("年龄必须是正整数"), email: z.string().email("邮箱格式不正确") }); // 推导TS类型,保留编译时类型提示 type ExampleRequest = z.infer<typeof ExampleRequestSchema>;
2. Lambda中实现校验与响应逻辑
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => { try { // 解析请求体 const requestBody = JSON.parse(event.body || "{}"); // 执行参数校验 const validatedData = ExampleRequestSchema.parse(requestBody); // 执行业务逻辑 return { statusCode: 200, body: JSON.stringify({ message: "请求成功", data: validatedData }) }; } catch (error) { // 捕获参数校验错误,返回400(符合HTTP状态码规范) if (error instanceof z.ZodError) { return { statusCode: 400, body: JSON.stringify({ error: "参数格式错误", details: error.issues.map(issue => `${issue.path.join('.')}: ${issue.message}`) }) }; } // 其他服务端内部错误返回500 return { statusCode: 500, body: JSON.stringify({ error: "服务端内部错误" }) }; } };
3. CDK配置API Gateway(确保响应透传)
Lambda返回的statusCode会被API Gateway默认透传,若需规范响应模型,可通过CDK配置:
import { RestApi, LambdaIntegration } from 'aws-cdk-lib/aws-apigateway'; import { Function, Runtime, Code } from 'aws-cdk-lib/aws-lambda'; import { Stack, Construct, StackProps } from 'aws-cdk-lib'; export class ApiStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); // 创建Lambda函数 const exampleLambda = new Function(this, 'ExampleLambda', { runtime: Runtime.NODEJS_18_X, code: Code.fromAsset('lambda'), handler: 'example.handler' }); // 创建API Gateway const api = new RestApi(this, 'ExampleApi'); // 配置/example端点与POST方法 const exampleResource = api.root.addResource('example'); exampleResource.addMethod('POST', new LambdaIntegration(exampleLambda), { methodResponses: [ { statusCode: '200' }, { statusCode: '400' }, { statusCode: '500' } ] }); } }
关键注意事项
- 避免误用Interface:TS Interface仅在编译时生效,无法实现运行时参数校验,必须搭配运行时逻辑。
- 规范状态码:参数错误应返回
400 Bad Request,而非500 Internal Server Error,符合HTTP协议语义。 - CDK简化配置:API Gateway默认会透传Lambda的响应状态码,无需复杂映射即可直接返回给请求方。
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

