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