Swagger UI via AWS API Gateway and AWS CDK

Aurelia Fenderson-Peters
2 min readSep 21, 2022

There are a bunch of sites that will tell you how to do a Swagger UI in Lambda. This one is nice enough to have a publicly available application you can deploy from AWS SAR. This one tells you how to do it in S3. But none that I’ve found tell you how to do it in AWS CDK. I aim to remedy that.

The whole stack is available at https://github.com/PopeFelix/swagger-ui-apigateway-example-with-typescript-and-cdk if you’d like to skip ahead. :)

Now, you might naively think that all you have to do is write a Lambda like so and you’ll be good to go:

import 'source-map-support/register'
import express from 'express'
import serverlessExpress from '@vendia/serverless-express'
import swaggerUi from 'swagger-ui-express'
import { Handler } from 'aws-lambda'
const app = express()
const url = 'https://petstore.swagger.io/v2/swagger.json'
export const handler: Handler = async (event, context, callback) => {
const resource = event.resource
const path = event.path
app.use('/', swaggerUi.serve, swaggerUi.setup({ url }))
const handler = serverlessExpress({ app })
return await handler(event, context, callback)
}

And in fact, that Lambda is fine. That’s just what you need for the Swagger UI to work flawlessly. The tricky bit is in the CDK deployment.

Normally, to deploy a Lambda, you’d do something like this:

const swaggerLambda = new cdk.aws_lambda_nodejs.NodejsFunction(
this,
'swagger',
{
entry: path.join(__dirname, '../lambda/swagger/index.ts')
}
)

And that’s exactly what I did, and it didn’t work. Anything I requested via the Swagger endpoint besides swagger-ui-init.js would return the Swagger UI HTML. It turns out that this was because CDK bundles all of your compiled Typescript together into one big file when it deploys a Lambda. This is great for efficiency, but not so good when modules like swagger-ui-express are looking for actual system paths. The solution? Set the bundling options like so:

const swaggerLambda = new cdk.aws_lambda_nodejs.NodejsFunction(
this,
'swagger',
{
entry: path.join(__dirname, '../lambda/swagger/index.ts'),
bundling: {
nodeModules: ['swagger-ui-express', 'express'],
},
}
)

That nodeModules option tells CDK that swagger-ui-express and express need to be installed (i.e. npm i swagger-ui-express express) rather than bundled with the Lambda code.

And that’s it! Hope this helps!

--

--

Aurelia Fenderson-Peters

20+ years writing code of various sorts. Full of trans magic.