Ani Alaverdyan
Ani Alaverdyan

Reputation: 1637

Request validation using serverless framework

I am using serverless framework for the backend. How can I implement request validation? (do not want to write validation inside lambda functions).

Upvotes: 25

Views: 21077

Answers (5)

Ivan Mushketyk
Ivan Mushketyk

Reputation: 8285

This is now supported by Serverless framework, so there is no need to use external plugins.

To enable requests validation one need is to add the following to the serverless.yml:

  HttpHandler:
    handler: src/lambda/http/create.handler
    events:
      - http:
          method: post
          path: items
          request:
            schemas:
              application/json: ${file(models/create-todo-model.json)}

Instead of keeping the file location directly under application/json you can also keep the name of the model after defining it under serverless.yml file's apiGateway section. link to documentation

Kindly note that, as of Feb-2022, serverless-offline plugin is not validating the http.request.schemas in your local. Though they are supporting deprecated version http.request.schema.

Upvotes: 36

SYED FAISAL
SYED FAISAL

Reputation: 519

Request validation using serverless

plugins:
  - serverless-python-requirements
  - serverless-wsgi
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation
  
provider:
  name: aws
  runtime: python3.8
  region: us-east-1

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get
  likes:
    handler: handler.likes
    events:
      - http:
          path: /likes
          method: get
          integration: lambda
          reqValidatorName: xMyRequestValidator
          request:
            passThrough: NEVER
            parameters:
              querystrings:
                userid: true
                activityid: true
            template:
              application/json: '{ "userid":"$input.params(''userid'')","activityid":"$input.params(''activityid'')"}'
          response:
            headers:
              Content-Type: "'application/json'"

custom:
  wsgi:
    app: handler.app
    pythonBin: python # Some systems with Python3 may require this
    packRequirements: false
  pythonRequirements:
    dockerizePip: non-linux
resources:
  Resources:
    xMyRequestValidator:  
      Type: "AWS::ApiGateway::RequestValidator"
      Properties:
        Name: 'my-req-validator'
        RestApiId: 
          Ref: ApiGatewayRestApi
        ValidateRequestBody: true
        ValidateRequestParameters: true 

Upvotes: -1

st.huber
st.huber

Reputation: 1545

In case you are like me and you don't want to add plugins as suggested in "https://stackoverflow.com/questions/49133294/request-validation-using-serverless-framework".

If you set parameters as required and want to validate them, you must add a request validator to your serverless.yml

Resources:
  ParameterRequestValidator:
    Type: AWS::ApiGateway::RequestValidator
    Properties:
      Name: ParameterRequestValidator
      RestApiId:
        Ref: ApiGatewayRestApi
      ValidateRequestBody: false
      ValidateRequestParameters: true

  ApiGatewayMethodNameOfYourApiLookItUpInYourTemplate:
    Properties:
      RequestValidatorId:
        Ref: ParameterRequestValidator

The method you want to validate will be named something like ApiGateway<Method><Get | Post | Patch | Put | Delete >:. You can look the name up when you package your serverless functions in the created template files.

Courtesy for this solutions goes to https://github.com/serverless/serverless/issues/5034#issuecomment-581832806

Upvotes: 2

tracyIan
tracyIan

Reputation: 41

As Ivan indicated, there is no need for external plugins as this is supported by the Serverless framework. However, I think the way to configure this has changed.

functions:
  create:
    handler: posts.create
    events:
      - http:
          path: posts/create
          method: post
          request:
            schema:
              application/json: ${file(create_request.json)}

This example was taken from: https://www.serverless.com/framework/docs/providers/aws/events/apigateway/#request-schema-validators

Upvotes: 4

Nicholas Sizer
Nicholas Sizer

Reputation: 3550

To implement request validation using serverless you need to do a couple of things: Include your model/header definitions in your stack, and then tell API gateway to use them for request validation.

You'll need to install the following packages:

And then you'll need to include them in your serverless.yml:

plugins:
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation

Note: below is only a quick run-down of how to incorporate the packages. Visit the packages' documentation pages for more comprehensive examples...

  1. Provide API gateway with a description of your models / headers.

    You can import json schemas for your models, and declare http headers using the serverless-aws-documentation plugin. Here's how you'd add a model to your serverless.yml:

    custom:
      documentation:
        api:
          info:
            version: v0.0.0
            title: Some API title
            description: Some API description
        models:
          - name: SomeLambdaRequest
            contentType: application/json
            schema: ${file(models/SomeLambdaRequest.json)} # reference to your model's json schema file. You can also declare the model inline.
    

    And here's how you'd reference the model in your lambda definition:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              documentation:
                summary: some summary
                description: some description
                requestBody:
                  description: some description
                requestModels:
                  application/json: SomeLambdaRequest
    

    You can also declare request headers against your lambda definition like so:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              documentation:
                summary: some summary
                description: some description
                requestHeaders:
                  - name: x-some-header
                    description: some header value
                    required: true # true or false
                  - name: x-another-header
                    description: some header value
                    required: false # true or false
    
  2. Tell API gateway to actually use the models for validation

    This part makes use of the serverless-reqvalidator-plugin package, and you need to add AWS::ApiGateway::RequestValidator resources to your serverless.yml file. You can specify whether you want to validate request body, request headers, or both.

    resources:
      Resources:
        onlyBody:
          Type: AWS::ApiGateway::RequestValidator
          Properties:
            Name: 'only-body'
            RestApiId:
              Ref: ApiGatewayRestApi
            ValidateRequestBody: true # true or false
            ValidateRequestParameters: false # true or false
    

    And then on individual functions you can make use of the validator like so:

    functions:
      someLambda:
        handler: src/someLambda.handler
        events:
          - http:
              # ... snip ...
              reqValidatorName: onlyBody # reference and use the 'only-body' request validator
    

Put all together your lambda definition would end up looking a little like this:

functions:
  someLambda:
    handler: src/someLambda.handler
    events:
      - http:
          # ... snip ...
          reqValidatorName: onlyBody # reference and use the 'only-body' request validator
          documentation:
            summary: some summary
            description: some description
            requestBody:
              description: some description
            requestModels:
              application/json: SomeLambdaRequest
            requestHeaders:
              - name: x-some-header
                description: some header value
                required: true # true or false
              - name: x-another-header
                description: some header value
                required: false # true or false

Upvotes: 35

Related Questions