如何为AWS::Serverless::Api的GET查询参数添加高级验证?
实现AWS API Gateway查询参数高级验证的方法
问题根源
你当前使用的aws_proxy集成模式会让API Gateway直接将请求转发给Lambda,跳过所有基于OpenAPI Schema的高级参数校验,仅会检查参数是否存在。这就是你定义的minimum、enum等规则不生效的核心原因。
解决方案
方案1:改用非Proxy集成模式
如果不需要完整的请求上下文转发,可以将集成类型改为aws而非aws_proxy,这样API Gateway会严格执行你在OpenAPI Schema中定义的所有校验规则:
x-amazon-apigateway-integration: credentials: !Ref APIGatewayRole httpMethod: "POST" uri: Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SearchFunction.Arn}/invocations" passthroughBehavior: "when_no_match" type: "aws" # 替换aws_proxy为aws requestTemplates: application/json: | { "text": "$input.params('text')", "page": $input.params('page'), "hitsPerPage": $input.params('hitsPerPage'), "subscription": "$input.params('subscription')", "distributionTenant": "$input.params('distributionTenant')" }
这种方式下,API Gateway会自动校验查询参数的类型、最小值、枚举值等,不符合规则的请求会直接返回400错误,无需Lambda处理。
方案2:在Lambda函数内实现参数校验
如果必须使用aws_proxy模式(比如需要完整的请求上下文),可以在Lambda函数内部添加参数校验逻辑,借助JSON Schema验证库实现:
以Python为例:
import jsonschema from jsonschema import validate def validate_query_params(params): # 转换字符串类型的数字参数为整数 try: params["page"] = int(params["page"]) params["hitsPerPage"] = int(params["hitsPerPage"]) except (KeyError, ValueError): return False, "page或hitsPerPage必须为有效整数" schema = { "type": "object", "properties": { "text": {"type": "string"}, "page": {"type": "integer", "minimum": 1}, "hitsPerPage": {"type": "integer", "minimum": 1}, "subscription": {"type": "string", "enum": ["PLUS", "FREE", "HD"]}, "distributionTenant": {"type": "string", "minLength": 4} }, "required": ["text", "page", "hitsPerPage", "subscription", "distributionTenant"] } try: validate(instance=params, schema=schema) except jsonschema.exceptions.ValidationError as err: return False, err.message return True, "" def lambda_handler(event, context): query_params = event.get("queryStringParameters", {}) valid, message = validate_query_params(query_params) if not valid: return { "statusCode": 400, "body": f"参数校验失败: {message}" } # 执行后续业务逻辑
方案3:使用API Gateway的Lambda请求验证器
创建专门的Lambda验证函数,通过API Gateway的请求验证器配置,在请求到达主Lambda前执行校验:
- 编写Lambda验证函数,逻辑同方案2的校验逻辑,校验通过返回
{"isValid": true},失败返回{"isValid": false, "errorMessage": "具体错误信息"} - 在CloudFormation的API定义中关联该验证器:
x-amazon-apigateway-request-validators: custom-param-validator: validateCustomRequest: true x-amazon-apigateway-request-validator: "custom-param-validator" x-amazon-apigateway-custom-authorizer: type: "REQUEST" authorizerUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ParamValidatorFunction.Arn}/invocations" authorizerResultTtlInSeconds: 300
这种方式既保留aws_proxy模式,又能在API Gateway层面拦截无效请求。
注意事项
- 方案1需要手动编写请求模板映射参数,无法直接获取完整请求上下文
- 方案2和3需自行处理参数类型转换(API Gateway会将所有查询参数以字符串形式传递)
内容的提问来源于stack exchange,提问作者BigButovskyi
相关产品推荐
相关产品推荐

