AWS CDK Api Gateway with Swagger
April 5, 2020Ahoi AWS'ler and Swagger fans
In the last post I showed how AWS CDK can be used as a welcome alternative to YAML for describing your cloud infrastructure. Working on my CDK project from I encountered a problem handling Swagger files. But first I want to explain what the Swagger definitions are. It should also be said that the new version of Swagger has been called OpenApi since 2018. When using AWS API Gateway, it is convenient to use Swagger for parameter validation such as Query, Path and Body Parameter. What exactly Swagger is and why I think it's so great I describe in the next section.
What is Swagger
Swagger is a YAML or JSON template language for describing RESTful APIs. Following I describe what is great about Swagger. First of all, the templates are extremely suitable as documentation about the API itself, because a stylish looking HTML UI can be generated out of the template, which describes the API endpoints very well. Such an UI can be seen in the cover of this blog post. Even more brilliant is the UI that can be used directly to test the endpoints, i.e. to send and receive requests and responses. Many API interfaces, like the AWS API Gateway, offer the parameter validation of requests with using Swagger. I give a little example for what I mean by parameter validation using the following example:
parameters:
- in: query
name: userId
description: Get items of that user
required: true
type: string
Here you can see a parameter of the type query. That means it would look something like this in the URL
http://<url>/items?userId=martin
With parameter validation, I can then define certain properties of the parameter, such as the name userId, whether it is required and what type the value should be, in our case as of the type string.
Another very powerful feature is that it is possible to generate client libaries from the Swagger definition (https://swagger.io/tools/swagger-codegen/). For example, Alfresco does this with the API Explorer (For more information, see GitHub Api-Explorer) and ADF (or ADF JS Github). There, for example, the Swagger File becomes the JavaScript API Library generated, which can be used as a wrapper for the API requests and is also in ADF Components Github.
It's also cool, Postman offers an import feature for Swagger definitions. Then a collection is created immediately. This is very handy if you want to start writing the requests in Postman.
AWS Api Gatway with Swagger
All the features from the previous section sound very tempting, don't they? How nice that AWS API Gateway also offers to extract Swagger definitions from its deployments and also to import it using CloudFormation or CDK. Unfortunately in connection with AWS CDK, extracted Swagger files are not so easy to reuse for their description. The biggest problem is that if, for example, a lambda is updated, its ARN also changes. However, the Swagger Files extracted from the API Gateway use exactly these ARNs when Lambda is used as a backend implementation for an endpoint. And since the ARN changes, they are outdated in the swagger file. Below is a Swagger Snippet and there you can see the Arn I'm talking about behind the uri keyword.
paths:
/ items:
get:
responses:
'200':
description: Ok
content: {}
'401':
description: Authorization information is missing or invalid
content: {}
x-amazon-apigateway-integration:
uri:> -
arn: aws: apigateway: [secure]: lambda: path/2015-03-31/functions/arn: aws: lambda: [secure]: [secure]: function: ApiLambdaCrudDynamoDBExam-getAllItemsFunction0B7A9-1KKCGIJ01C3NI/invocations
passthroughBehavior: when_no_match
httpMethod: POST
type: aws_proxy
parameters:
- $ ref: '#/parameters/alfUserIdParam'
x-amazon-apigateway-request-validator: Validator
The AWS CDK team knows about this problem and it is on the roadmap. So hopefully if you read this post the following workaround is no longer necessary. For completeness, I list the related issues here:
https://github.com/aws/aws-cdk/issues/723 https://github.com/aws/aws-cdk/issues/1461
Workaround
To solved the problem with deploying CDK twice. The first deploy does not use a swagger definition but the second does. It is really interesting how I generated the Swagger file. In the following I try to describe the process, but please also look into my GitHub repo (there in .travis) for how I implemented this workaround.
- I deploy or Swagger File with:
export WITH_SWAGGER = 'false' && cdk deploy --require-approval never
WITH_SWAGGER is an env variable in the CDK Deployment File index.ts. This means that no swagger file is used programmatically for the deployment.
- Now I can use the AWS CLI to extract the swagger file from the API gateway:
aws apigateway get-export --parameters extensions = 'integrations' --rest-api-id $ REST_API_ID --stage-name prod --export-type swagger --accepts application/yaml tmp/swagger_new.yaml
The generated Swagger File tmp/swagger_new.yaml looks something like this:
swagger: '2.0'
info:
version: '2020-03-29T16: 59: 22Z'
title: Items Service
host: hjtiuj2ou1.execute-api. [secure] .amazonaws.com
basePath:/prod
schemes:
- https
paths:
/ items:
get:
responses:
'200':
description: Ok
'401':
description: Authorization information is missing or invalid
x-amazon-apigateway-integration:
uri:> -
arn: aws: apigateway: [secure]: lambda: path/2015-03-31/functions/arn: aws: lambda: [secure]: [secure]: function: ApiLambdaCrudDynamoDBExam-getAllItemsFunction0B7A9-1MLKSKO1RUL3I/invocations
passthroughBehavior: when_no_match
httpMethod: POST
type: aws_proxy
x-amazon-apigateway-request-validator: Validator
post Office:
...
- It looks very good. However, the parameter validation is still missing. For this a second Swagger definition has to be created manually templates/swagger_validations.yaml and looks something like this:
paths:
/ items:
get:
parameters:
- Name: alfUserId
in: query
required: false
type: string
$ ref: '#/parameters/alfUserIdParam'
- What we want now is a merge of both swagger files. NPM offers a useful tool for merging YAML files:
npm i -g merge-yaml-cli
The Swagger definition tmp/swagger_full.yaml now contains the current LambdaUri and the parameter validation:
swagger: '2.0'
info:
version: '2020-03-29T16: 59: 22Z'
title: Items Service
host: hjtiuj2ou1.execute-api. [secure] .amazonaws.com
basePath:/prod
schemes:
- https
paths:
/ items:
get:
parameters:
- Name: alfUserId
in: query
required: false
type: string
$ ref: '#/parameters/alfUserIdParam'
responses:
'200':
description: Ok
'401':
description: Authorization information is missing or invalid
x-amazon-apigateway-integration:
uri:> -
arn: aws: apigateway: [secure]: lambda: path/2015-03-31/functions/arn: aws: lambda: [secure]: [secure]: function: ApiLambdaCrudDynamoDBExam-getAllItemsFunction0B7A9-1MLKSKO1RUL3I/invocations
passthroughBehavior: when_no_match
httpMethod: POST
type: aws_proxy
x-amazon-apigateway-request-validator: Validator
post Office:
...
- Now this swagger file can be used in the second CDK deployment:
export WITH_SWAGGER = 'true' && cdk deploy --require-approval never
Attention!: Always take care with creating a new stage deployment in AWS API Gateway. I do this in Travis with the AWS CLI:
aws apigateway create-deployment --rest-api-id $ REST_API_ID --stage-name prod
Summary
Swagger Definitions are ideal for creating, editing, documenting and testing APIs such as those from AWS Api Gateway. They are not only useful directly in the backend. As well they are suited in the frontend because Swagger can generate amazing looking and useful Swagger UI to understand the backend better in a way shorter time.
To the wonderful readers of this article I'm saying that feedback of any kind is welcome. In the future I will try to include a discussion and comment feature here. In the meantime, please feel free to send me feedback via my social media accounts such as Twitter or FaceBook. Thank you very much :).
I love to work on Content Management Open Source projects. A lot from my stuff you can already use on www.github.com/mmuller88 . If you like my work there and my blog posts, please consider supporting me on Patreon: