Created
June 11, 2019 13:52
-
-
Save abbottdev/17379763ebc14a5ecbf2a111ffbcdd86 to your computer and use it in GitHub Desktop.
Typescript example for creating aws cdk resources using a swaggerfile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as cdk from '@aws-cdk/cdk'; | |
import * as SwaggerParser from "swagger-parser"; | |
import convertSwaggerToCdkRestApi from "./swaggerHelper"; | |
SwaggerParser | |
.parse("./swagger.yaml") | |
.then(swagger => { | |
const app = new cdk.App(); | |
let apiGateway = new apigateway.RestApi(this, "My Rest API", { | |
restApiName: "My Rest API", | |
}); | |
convertSwaggerToCdkRestApi(this, apiGateway, swagger); | |
app.synth(); | |
}); | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
swagger: "2.0" | |
info: | |
version: "1.0" | |
title: "Hello World API" | |
paths: | |
/hello/{userName}: | |
get: | |
x-cdk-lambda-code: ./functions/helloWorldLambda/ | |
x-cdk-lambda-handler: helloWorldLambda | |
x-cdk-lambda-name: helloWorldGetLambda | |
description: Returns a greeting to the user! | |
parameters: | |
- name: userName | |
in: path | |
required: true | |
type: string | |
responses: | |
200: | |
description: Returns the greeting. | |
schema: | |
type: string | |
400: | |
description: Bad Request |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as cdk from "@aws-cdk/cdk"; | |
import * as apigateway from '@aws-cdk/aws-apigateway'; | |
import * as lambda from '@aws-cdk/aws-lambda'; | |
import { LambdaIntegration } from "@aws-cdk/aws-apigateway"; | |
export default function convertSwaggerToCdkRestApi(scope:cdk.Construct, apiGateway:apigateway.RestApi, swaggerApi: any) { | |
let createdLambdas:Map<string, lambda.Function> = new Map<string, lambda.Function>(); | |
let paths = Object.keys(swaggerApi.paths); | |
paths.forEach(pathName => { | |
const resource = apiGateway.root.resourceForPath(pathName); | |
const methods = Object.keys(swaggerApi.paths[pathName]); | |
methods.forEach(methodName => { | |
let endpoint = swaggerApi.paths[pathName][methodName]; | |
let backingLambda: lambda.Function; | |
if (createdLambdas.has(endpoint["x-cdk-lambda-name"]) === false) { | |
createdLambdas.set(endpoint["x-cdk-lambda-name"], | |
new lambda.Function(scope, endpoint["x-cdk-lambda-name"], { | |
code: lambda.Code.asset(endpoint["x-cdk-lambda-code"]), | |
handler: endpoint["x-cdk-lambda-handler"], | |
runtime: lambda.Runtime.Go1x | |
}) | |
); | |
} | |
backingLambda = createdLambdas.get(endpoint["x-cdk-lambda-name"])!; | |
let integrationParameters:any = undefined; | |
let methodParameters:any = undefined; | |
if (endpoint.parameters && endpoint.parameters.length) { | |
let parameters:any[] = endpoint.parameters; | |
integrationParameters = {}; | |
methodParameters = {}; | |
parameters.forEach(swaggerParameter => { | |
integrationParameters[`integration.request.${swaggerParameter.in}.${swaggerParameter.name}`] = `method.request.${swaggerParameter.in}.${swaggerParameter.name}`; | |
methodParameters[`method.request.${swaggerParameter.in}.${swaggerParameter.name}`] = true; | |
}); | |
} | |
resource.addMethod(methodName, | |
new LambdaIntegration(backingLambda, { | |
requestParameters: integrationParameters | |
}), | |
{ | |
requestParameters: methodParameters | |
}); | |
}); | |
}); | |
} |
This is cool! I'd assume there are some packages that can generate the swagger.yml from typescript decorators? Any thoughts about how that could wedge into aws-cdk?
This example doesn't use the parameter type argument "type: string", is there a way to indicate parameter type and enable request parameter validation?
If you want the same idea thing but for a lambda and slightly simplified this is how I edited it (one backing lambda function)
import { RestApi } from '@aws-cdk/aws-apigateway';
import { Function } from '@aws-cdk/aws-lambda';
import { LambdaIntegration } from "@aws-cdk/aws-apigateway";
import { readFileSync } from 'fs';
import { safeLoad } from "js-yaml";
/**
* Add all methods in the swagger definition to the API GW instance with parameter validation
* @param apiGateway the apigw to add the swagger definition to
* @param lambda the lambda function backing the apigw
* @param swaggerPath the path to the swagger definition
*/
export default function addSwaggerDefToApiGw(apiGateway: RestApi, lambda: Function, swaggerPath: string) {
const swaggerApi = safeLoad(readFileSync(swaggerPath, 'utf8'));
const paths = Object.keys(swaggerApi.paths);
paths.forEach(pathName => {
const resource = apiGateway.root.resourceForPath(pathName);
const methods = Object.keys(swaggerApi.paths[pathName]);
methods.forEach(methodName => {
const endpoint = swaggerApi.paths[pathName][methodName];
let integrationParameters:any = undefined;
let methodParameters:any = undefined;
if (endpoint.parameters && endpoint.parameters.length) {
const parameters:any[] = endpoint.parameters;
integrationParameters = {};
methodParameters = {};
parameters.forEach(swaggerParameter => {
integrationParameters[`integration.request.${swaggerParameter.in}.${swaggerParameter.name}`] = `method.request.${swaggerParameter.in}.${swaggerParameter.name}`;
methodParameters[`method.request.${swaggerParameter.in}.${swaggerParameter.name}`] = true;
});
}
resource.addMethod(methodName,
new LambdaIntegration(lambda, {
requestParameters: integrationParameters
}),
{
requestParameters: methodParameters
});
});
});
}
Using .in
seems to only work when the OpenAPI parameter location (see Parameter Object section here) corresponds to the API Gateway request parameter location (see here).
- OpenAPI
path
=> API Gatewaypath
- OpenAPI
query
=> API Gatewayquerystring
- OpenAPI
header
=> API Gatewayheader
- OpenAPI
cookie
=> No API Gateway equivalent
Thanks for putting it together. Will this utility be able to also import an open API 3.0 file as an aws-cdk construct ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for gisting this