1

i'm trying to figure out the best way to define response/request models for my Lambda functions and API Gateway.

What am I trying to achieve?

What I want is to store all my models within my git repo for requests and responses, these will be deployed to API Gateway using the serverless-aws-documentation plugin.

So let's say there is a 500/400 error, the response would be formatted using this model, not the code. Let's focus on the error response, this should be like so:

"Error": {
  "type": "object",
  "properties": {
    "message": {
      "type": "string"
    },
    "type": {
      "type": "string"
    },
    "request-id": {
      "type": "string"
    }
  }
}

What I currently have

Below is what I have right now, which creates the models on my API Gateway just fine, however i'm currently formatting the response within code, ideally I would just throw an exception here and let the model handle for formatting?

unresolvedVariablesNotificationMode: error
useDotenv: true

provider:
  name: aws
  profile: ${opt:aws-profile, 'sandbox'}
  region: eu-west-2
  stage: ${opt:stage, 'dev'}
  lambdaHashingVersion: 20201221
  environment:
    TABLE_PREFIX: ${self:provider.stage}-${self:service}-
    API_ROOT: ${self:custom.domains.${self:provider.stage}}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeTable
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource:
        - Fn::GetAtt:
          - enquiriesTable
          - Arn
        - Fn::GetAtt:
          - vehiclesTable
          - Arn
plugins:
  - serverless-api-gateway-throttling
  - serverless-associate-waf
#  - serverless-domain-manager
  - serverless-reqvalidator-plugin
  - serverless-aws-documentation
  - serverless-webpack
  - serverless-dynamodb-local
  - serverless-offline

custom:
  apiGatewayThrottling:
    maxRequestsPerSecond: 10
    maxConcurrentRequests: 5
  webpack:
    includeModules: true
  dynamodb:
    stages: [ dev ]
    start:
      migrate: true
  documentation:
    models:
      -
        name: "ErrorResponse"
        description: "This is how an error would return"
        contentType: "application/json"
        schema: ${file(models/Error.json)}

functions:
  createEnquiry:
    handler: src/services/enquiries/create.handler
    environment:
      API_ROOT: ${self:custom.domains.${self:provider.stage}}
    events:
      - http:
          path: /
          method: POST
          reqValidatorName: onlyParameters
          documentation:
            requestModels:
              "application/json": "CreateRequest"
            methodResponses:
              -
                statusCode: "400"
                responseModels:
                  "application/json": "ErrorResponse"
resources:
  Resources:
    onlyParameters:
      Type: "AWS::ApiGateway::RequestValidator"
      Properties:
        Name: "only-parameters"
        RestApiId:
          Ref: ApiGatewayRestApi
        ValidateRequestBody: true
        ValidateRequestParameters: true
    enquiriesTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:provider.stage}-${self:service}-enquiries
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST
    vehiclesTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:provider.stage}-${self:service}-vehicles
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST

Can someone point me in the right direction to achieve what i'm attempting. So to have the models defined within the repo, and have these define the response rather than the Node.

Update

Just attempted the following from this link:

functions:
  createEnquiry:
    handler: src/services/enquiries/create.handler
    environment:
      API_ROOT: ${self:custom.domains.${self:provider.stage}}
    events:
      - http:
          path: /
          method: POST
          reqValidatorName: onlyParameters
          x-amazon-apigateway-integration:
            responses:
              ".*httpStatus\\\":404.*":
                statusCode: 404,
                responseTemplates:
                  application/json: "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n#set ($bodyObj = $util.parseJson($input.body))\n{\n  \"type\" : \"$errorMessageObj.errorType\",\n  \"message\" : \"$errorMessageObj.message\",\n  \"request-id\" : \"$errorMessageObj.requestId\"\n}"
export const handler: APIGatewayProxyHandler = async (event) => {
  return {
    statusCode: 400,
    body: 'Enquiry already exists'
  }

This still just returned the following response as a string:

Enquiryalreadyexists
Martyn Ball
  • 4,679
  • 8
  • 56
  • 126

0 Answers0