serverless-openapi-req-validation
v2.3.0
Published
Automatically generate an opeanpi file from your Serverless Framework config file to be used for validation inside your api gateway
Downloads
311
Readme
Serverless Openapi Req Validation
This plugin allows you to automatically generate an openapi specifications, describing your application endpoints. Additionally, it injects the necessary types and objects into the existing serverless configuration.
Install
yarn add --dev serverless-openapi-req-validation
# or
npm install -D serverless-openapi-req-validation
Add the following plugin to your serverless.yml
or serverless.ts
:
plugins:
- serverless-openapi-req-validation
plugins: ['serverless-openapi-req-validation'];
Usage
This plugin is designed to work with vanilla Serverless Framework. The plugin is split into two part:
- Openapi v3 generation
- Request validation with API GateWay
The openapi file can be generated by running sls generate-openapi
. The request validation can be toggled by uploadTypes
(default false).
Request Validation
If enabled the respective requestBody
types are transformed AWS::ApiGateway::Model
Cloudformation resources and injected in the same stack, so be in mind with the maximum resources per stack. Currently the request validation within API Gateway works with swagger v2.0. Due to the inherit difference between openapi 3 and 2, anyOf
constructs are not supported and skipped in the uploading phase. Meaning Union types are not yet supported and skipped in the uploading phase.
Config Options
All config options are optional. Defaults are shown in the table below.
custom:
autoOpenapi:
info:
title: 'string'
description: 'string'
apiType: 'http' | 'httpApi'
typeFiles: ['./src/types/typefile1.d.ts', './src/**/types.ts']
apiKeyHeaders: ['Authorization', 'anyOtherName']
outputDir: 'generated'
uploadTypes: true | false
compactOutput: true | false
useStage: true | false
basePath: '/string'
host: 'http://some-host'
excludeStages: ['production', 'anyOtherStage']
externalDocs:
url: http://some-doc
description: some-description
servers:
- url: http://some-server
description: some-description
openapiTags:
- some-tag
| Option | Description | Default | Example |
|-----------------|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------|----------------------------------------------------------------------|
| info
| Info object according to openapi specifications | { title: Serverless service name
, version: Current time
| See info-object |
| apiType
| API type for which your openapi file should be created for. Options are http
and httpApi
| httpApi
| |
| uploadTypes
| Boolean indicating to upload types to API Gateway on deployment via designated serverless event fields | false
| |
| compactOutput
| During node construction, use anchors and aliases to keep strictly equal non-null objects as equivalent in YAML | false
| description: *a2 |
| typeFiles
| Array of strings which defines where to find the typescript types to use for the request and response bodies | ['./src/types/api-types.d.ts']
| |
| apiKeyHeaders
| Array of strings used to define API keys used in auth headers | []
| apiKeyHeaders: ['Authorization', 'x-api-key']
|
| useStage
| Boolean to either use current stage in beginning of path or not | false
| true
=> dev/openapi
for stage dev |
|
basePath | String that can be prepended to every request. Should include leading
/ | - |
/some-base=>
http://localhost/some-base/my-endpoint |
|
host | String that overrides the host. With this you can set your custom domain for your application endpoints | - |
http://some-host=>
{http://some-host}/my-endpoint |
|
excludeStages| Array of strings that contains stages in which openapi should **not** be created and injected in. |
[] | |
|
externalDocs | Object containing the
urland optional
descriptionof where external documentation is located | - |
externalDocs: { url: 'some-url', description: 'some-description' }|
|
servers | Array of server objects |
[] |
servers: [ { url: 'some-url', description: 'some-description' } ]` |
Adding more details
The default openapi file from vanilla Serverless framework will have the correct paths and methods but no details about the requests or responses.
API Summary and Details
The optional attributes summary
and description
can be used to describe each HTTP request in Openapi.
openapiTags
is an optional array that can be used to group HTTP requests with a collapsible name
(i.e. grouping two endpoints GET /dogs
and POST /dogs
together).
If not specified, all HTTP requests will be grouped under default
.
http:
summary: 'This is a cool API'
description: 'Cool API description is here'
openapiTags: ['Dogs']
Adding Data Types
This plugin uses typescript types to generate the data types for the endpoints. By default, it pulls the types from src/types/api-types.d.ts
.
You can then assign these typescript definitions to requests as requestBody
on the http or https config, or to the response as seen just below.
Responses
You can also add expected responses to each of the http endpoint events. This is an object that contains the response code with some example details:
responses:
# response with description and response body
200:
description: 'this went well'
bodyType: 'helloPostResponse'
# response with just a description
400:
description: 'failed Post'
# shorthand for just a description
502: 'server error'
}
Post request expected body
When you create a POST
or PUT
endpoint, you expect to receive a specific structure of data as the body of the request.
You can do that by adding a requestBody
to the http event:
http:
path: 'hello'
method: 'post'
requestBody: 'helloPostBody'
or with an additional description:
http:
path: 'hello'
method: 'post'
requestBody:
bodyType: 'helloPostBody'
description: 'Some Description'
Query String Parameters
If you want to specify the query string parameters on an endpoint you can do this by adding an object of queryStringParameters
to the event. This has two required properties of required
and type
as well as an optional description
.
http:
path: 'goodbye'
method: 'get'
queryStringParameters:
bob:
required: true
type: 'string'
description: 'bob'
count:
required: false
type: 'integer'
If no queryStringParameters
are defined, the plugin will do its best to generate params based on any Serverless request.parameters.querystrings
that are defined.
Alternatively, one can rely on the default implementation of Serverless request.parameters.querystrings
. For both scenarios the plugin will manage the injection of the final template for request validation.
Header Params
Works the same way as queryStringParameters
, but for headers.
To use it, just define it under headerParameters
:
http:
path: 'goodbye'
method: 'get'
headerParameters:
bob:
required: true
type: 'string'
description: 'bob'
count:
required: false
type: 'integer'
If no headerParameters
are defined, the plugin will do its best to generate headers based on any Serverless request.parameters.headers
that are defined.
Alternatively, one can rely on the default implementation of Serverless request.parameters.headers
. For both scenarios the plugin will manage the injection of the final template for request validation.
Path Parameters
Path parameters are resolved first by looking at request.parameters.paths
, and then by resolving any additional parameters in the http event path (i.e. /{id}
). By default, the path will be determined during runtime from your Serverless config if omitted in request.parameters.paths
. Thus it is for no need to specify this parameter.
Exclude an endpoint
You can exclude some endpoints from the openapi generation by adding exclude
to the http event:
http:
path: 'hello'
method: 'post'
exclude: true
Exclude from validation
Alternatively, you can solely exclude some endpoints to be uploaded to API Gateway for validation by adding disableValidation
to the http event:
http:
path: 'hello'
method: 'post'
disableValidation: true
Custom operationId
You can override the automatically generated operationId by adding the operationId
property to the http event. This can be useful when using code generators.
http:
path: 'hello'
method: 'post'
operationId: 'postHello'
Annotations
The schema generator uses JSDoc
for typescript, which is able to convert annotations to JSON schema properties. See their jsdoc for more examples
For example
export interface Shape {
/**
* The size of the shape.
*
* @pattern ^[a-zA-Z]+$
*/
size: string;
}
will be translated to
{
"Shape": {
"properties": {
"size": {
"description": "The size of the shape.",
"pattern": "^[a-zA-Z]+$",
"type": "string"
}
},
"type": "object"
}
}
Automated Descriptions
Serverless
Descriptions in your openapi specifications can be added as follows:
http:
path: 'path'
method: post
description: "Custom path description"
summary: "Custom path summary"
queryStringParameters:
parameter:
type: 'string'
description: 'Custom parameter description'
requestBody:
bodyType: SomeBody
description: 'Custom requestbody description'
responses:
202:
description: "Custom response description"
The above will result in:
{
"paths": {
"/path": {
"post": {
"summary": "Custom path summary",
"parameters": [
{
"in": "query",
"name": "parameter",
"description": "Custom parameter description",
}
],
"requestBody": {
"description": "Custom requestbody description",
},
"responses": {
"202": {
"description": "Custom response description"
}
},
"description": "Custom path description"
}
}
}
}
Typescript
Multiline comment statements are automatically used in the respective component's schema description. The following example:
/**
* This is a custom shape
*/
export interface Shape {
/**
* The size of the shape.
*/
size: number;
type: string;
}
, will result in the following openapi schema:
{
"Shape": {
"description": "This is a custom shape",
"title": "Shape",
"properties": {
"size": {
"description": "The size of the shape.",
"type": "number"
}
},
"type": "object"
}
}