【问题标题】:Use Swagger API validation with Serverless Framework将 Swagger API 验证与无服务器框架一起使用
【发布时间】:2019-01-27 19:50:39
【问题描述】:

我想向无服务器 aws-nodes 模板添加一个 api 验证,但到目前为止我测试过的任何东西都没有很好的效果。

我目前的方法是使用包含我的验证模型的 yml/json swagger 定义覆盖现有的由无服务器框架生成的 api-gateway。当我在 API-Gateway UI 中测试它时,这对我有用,但是在外部请求中,api 不会验证对 lambda-proxy 的请求。

当我使用普通 lambda 时,api 网关也会通过请求正文而不进行验证或转换。

我当前带有验证的 swagger api 定义:

  swagger: "2.0"
  info:
    title: feedback
    version: '1.0'

  schemes:
  - https
  produces:
  - application/json
  x-amazon-apigateway-api-key-source : HEADER

  x-amazon-apigateway-request-validators:
    full:
      validateRequestBody: true
      validateRequestParameters: true
    body-only:
      validateRequestBody: true
      validateRequestParameters: false
  x-amazon-apigateway-request-validator: full

  # Custom 400 response with validation feedback
  x-amazon-apigateway-gateway-responses:
    BAD_REQUEST_BODY:
      statusCode: 400
      type:
        application/json: 
      responseTemplates:
      application/json:
        |-
          {
              "message": $context.error.messageString,
              "validation":  "$context.error.validationErrorString",
              "statusCode": "'400'"
          }

  # request structure
  paths:
    /feedback:
      post:
        # validation definition
        x-amazon-apigateway-request-validator: body-only
        parameters:
        - in: body
          name: Create ...
          required: true
          schema: 
            "$ref": "#/definitions/Model"
        responses:
          '200':
            description: validation succeeded
          '400':
            description: validation failed

        x-amazon-apigateway-integration:

          uri: "arn:aws:apigateway:{api-region}:lambda:path/2015-03-31/functions/arn:aws:lambda:{lambda-region}:{konto-id}:function:{function-name}/invocations"

          passthroughBehavior: when_no_match
          httpMethod: POST
          requestTemplates:
            application/json: '{"statusCode": 200}'
          type: aws
      get:
        responses:
          '201':
            description: list all Data
            content:
              application/json:
                schema:
                  type: array
                  items:
                    feedback:
                      $ref: "#/definitions/Model"
          '401':
            $ref: "#/definitions/UnauthorizedError"
        x-amazon-apigateway-integration:
          uri: "arn:aws:apigateway:{api-region}:lambda:path/2015-03-31/functions/arn:aws:lambda:{lambda-region}:{konto-id}:function:{function-name}/invocations"
          passthroughBehavior: never
          httpMethod: POST
          type: aws_proxy

  # definition of the request/respons model with validation
  definitions:
      Model:
        type: object
        properties:
          topic:
            $ref: "#/definitions/Topic"
          text:
            type: string
            minLength: 1
            maxLength: 250
        required:
          - topic
          - text
      Topic:
            type: string
            enum: 
              - xyz

我的 serverless.yml 中的 api 定义

functions:
  create:
    handler: feedback/create.create
    events:
     - http:
         path: feedback
         method: post
 list:
    handler: feedback/list.list
    events:
      - http:
          path: feedback
          method: get 

lambda 函数仅从 DynamoDB 读取/写入反馈

有人知道如何在不使用小插件 (serverless-reqvalidator-plugin) 的情况下向我的无服务器项目添加某种 api 验证,或者如何解决数据转换问题?

【问题讨论】:

    标签: aws-lambda swagger aws-api-gateway serverless-framework request-validation


    【解决方案1】:

    好的,验证适用于内部测试但不适用于外部请求的问题的解决方案非常明显。我忘了部署新的 api-definition。

    aws apigateway create-deployment --rest-api-id {api-id} --stage-name dev
    

    我还更改了我的 API 定义。我现在将一个普通的 lambda 整合到我的 Post 请求中。这是唯一的方法,我可以确保只有 json 内容得到验证,然后传递给 lamda 函数。因为我没有使用 lambda-proxy,所以请求事件是从 api-gateway 转换而来的,所以我必须定义一个请求模板,将整个请求正文放入一个新请求中。

     requestTemplates:
          application/json: '{"statusCode": 202, "body": $input.body}'
    

    通过这种方式,我还将 lambda 响应转换为带有 Cors 标头的预定义 api 响应。

    我的最终解决方案是:

    1:写一个swagger api定义:

      swagger: "2.0"
      info:
        title: xxxxxx
        version: '0.0.0'
    
      schemes:
      - https
      produces:
      - application/json
    
      x-amazon-apigateway-api-key-source : HEADER
    
      # Define which parts of the request should be validated
      x-amazon-apigateway-request-validators:
        full:
          validateRequestBody: true
          validateRequestParameters: true
        body-only:
          validateRequestBody: true
          validateRequestParameters: false
    
      # Custom response model from the api-gateway that return validation error string 
      x-amazon-apigateway-gateway-responses:
        BAD_REQUEST_BODY:
          statusCode: 400
          type:
            application/json:
          responseParameters: # CORS Headers
              gatewayresponse.header.Access-Control-Allow-Credentials : "'true'"
              gatewayresponse.header.Access-Control-Allow-Origin : "'*'"
          responseTemplates:
          application/json: #must be an json string because otherwiese there are some transformation issues
            |-
              {
                  "message": $context.error.messageString,
                  "validation":  "$context.error.validationErrorString",
                  "statusCode": "400"
              }   
    
    
      paths:
        /feedback:
          options: 
            description:
              Enable CORS by returning correct headers
            tags:
              - CORS
            x-amazon-apigateway-integration:
              type: mock
              requestTemplates:
                application/json: |
                  {
                    "statusCode" : 200
                  }
              responses:
                "default":
                  statusCode: "200"
                  responseParameters: # CORS Headers
                    method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                    method.response.header.Access-Control-Allow-Methods : "'*'"
                    method.response.header.Access-Control-Allow-Origin : "'*'"
                  responseTemplates:
                    application/json: |
                      {}
            responses:
              200:
                description: Default response for CORS method
                headers:
                  Access-Control-Allow-Headers:
                    type: "string"
                  Access-Control-Allow-Methods:
                    type: "string"
                  Access-Control-Allow-Origin:
                    type: "string"
          post:
            # validation definition
            x-amazon-apigateway-request-validator: body-only
            parameters:
            - in: body 
              name: requestBody
              required: true
              content:
                application/json:
              schema: # validation model
                "$ref": "#/definitions/Model"
            responses: # response documentation
              '200':
                description: Create ......
                headers: # Header format for the CORS headers
                  Access-Control-Allow-Credentials:
                    type: "string"
                  Access-Control-Allow-Origin:
                    type: "string"
            x-amazon-apigateway-integration:
              responses:
                default:
                  statusCode: "200"
                  responseParameters: # CORS Header
                    method.response.header.Access-Control-Allow-Credentials : "'true'"
                    method.response.header.Access-Control-Allow-Origin : "'*'"
              uri: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::account-id}:function:{AWS::lambda-function-name}/invocations
              requestTemplates:
                application/json: '{"statusCode": 202, "body": $input.body}' 
              passthroughBehavior: never # only accept Json Data
              httpMethod: POST 
              type: aws 
    
          get:
            security: # X-API-Key
              - authorizer: [] 
            responses: 
              '200':
                description: ......
            x-amazon-apigateway-integration: 
              uri: "arn:aws:apigateway:xxx:lambda:path/2015-03-31/functions/arn:aws:lambda:xxx:xxxxxxx:function:function-name/invocations"
              httpMethod: POST
              type: aws_proxy 
    
      definitions:
        Model:
           # Swagger Model with validation
    
      securityDefinitions:
        authorizer :
          type : apiKey                         
          name : x-api-key                 
          in : header                           
    

    2:覆盖现有的 serverless api:

    aws apigateway put-rest-api --rest-api-id {api-id} --mode overwrite --body file://xxxx/api.yml
    

    3:别忘了部署新的api:

    aws apigateway create-deployment --rest-api-id {api-id} --region eu-central-1 --stage-name ...
    

    【讨论】:

      猜你喜欢
      • 2021-11-25
      • 2020-01-21
      • 1970-01-01
      • 2018-08-14
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 2020-12-10
      • 2016-12-25
      相关资源
      最近更新 更多