Starting AWS CDK with TypeScript. AWS Lambda + API Gateway
Tags: awscdk, aws, lambda, serverless
Published: 2023-02-12 00:47:58

## Environment

- AWS Cloud9

- CDK Version : 2.63.2

## Image Diagram
I would like to create a demo of a Lambda service that can be called via Amazon API Gateway using AWS CDK. The demo image is below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzielf9red7u1g0ajqmj.png)
So let's get your hands dirty!

## Creating a new CDK Project
We will be using AWS Cloud9 as our working environment. As the title says, we will create a project using TypeScript.
First, create a directory for the project we will use this time.

```
mkdir cdk-workshop && cd cdk-workshop
```
Create a TypeScript CDK project. (This will take a bit of time.)

```
cdk init sample-app --language typescript
```
You will see useful cdk commands like this. We will use these later.

```
## Useful commands

* `cdk deploy`      deploy this stack to your default AWS account/region
* `cdk diff`        compare deployed stack with current state
* `cdk synth`       emits the synthesized CloudFormation template
```
You will see the project directory created as shown in the figure below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1e0sbyjkgtu5fyq3aos6.png)

- `lib/cdk-workshop-stack.ts`:This file defines the main stack of the CDK application. This file is the main file to edit.

- `bin/cdk-workshop.ts`:This will be the entry point for the CDK application, loading the stack defined in lib/cdk-workshop-stack.ts.

- `cdk.json`:It defines how to RUN the app for the toolkit. In this case, it is written as npx ts-node bin/cdk-workshop.ts.

## Creating Lambda Function, API Gateway
### Clean up unnecessary code and deploy first time
The first step is to clean up some existing code that is not needed.
Open lib/cdk-workshop-stack.ts and clean up as follows, since SQS Queue and SNS topic are not needed for this demo.

```
import * as cdk from 'aws-cdk-lib';

export class CdkWorkshopStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // nothing here!
  }
}
```
The contents of the CDK are empty, but the AWS CloudFormation template is created (synthesize) from the contents described in the CDK, and when deploying to an AWS environment, even if the CDK is used, the CloudFormation template is deployed in the form of a CloudFormation template. 

```
cdk synth
```
The CloudFormation template has been created in the checkout folder.

Next, you can install a stack called "bootstrap" only for the first deployment. This stack contains resources used by the CDK Toolkit, such as the S3 bucket that holds the CloudFormation templates. 

```
cdk bootstrap
```
Now, let's deploy it!

```
cdk deploy
```
If you look at the CloudFormation console after a successful deployment, you see that the stack you created exists! (It means that the template created with cdk synth has been applied)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfy0yrkvim8agwop2tvk.png)

### Creating Hello Lambda function
Let's write the code for the Lambda function. We will do the following

1. Create a lambda directory in the same hierarchy as the bin and lib directories.

1. If a .gitignore file exists, add !lambda/*.js in the file.

1. Create the file lambda/hello.js and write the following code

```
exports.handler = async function(event) {
  console.log("request:", JSON.stringify(event, undefined, 2));
  return {
    statusCode: 200,
    headers: { "Content-Type": "text/plain" },
    body: `Hello, CDK! You've hit ${event.path}\n`
  };
};
```
### Add the created Lambda function to the stack
Add the lambda function you just created to the stack. import the CDK Library for Lambda, which is also needed to add the Lambda stack.

```
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';

export class CdkWorkshopStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // defines an AWS Lambda resource
    const hello = new lambda.Function(this, 'HelloHandler', {
      runtime: lambda.Runtime.NODEJS_16_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'hello.handler'
    });
  }
}
```
A few additional details about the above code

- The NodeJS (version 16) runtime is used.

- The handler of the Lambda function is written to be read from the lambda directory.

- The name of the handler is also the same as the handler in the created function.

Before deploying, take a look at the differences in the code. You can see the differences.

```
cdk diff
```
### Deploy

```
cdk deploy
```
If you look at the console after deploy, you will see that the hello.js Lambda function has been created and that the asset folder has also been created in the S3 bucket.
### Test
To test the created Lambda function, create and run a test using the "Amazon API Gateway AWS Proxy" template from the Lambda console.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dy99fxh7g1szc5ole5io.png)
Looks it works!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zj06d5mpw8nh0js45xqo.png)

### Creating a API Gateway
Next, we will create an API Gateway, a service that publishes a public endpoint on the Internet, and connect the API Gateway to Lambda so that it can receive requests from browsers and other devices.
The following is a code of the API Gateway.

```
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigw from 'aws-cdk-lib/aws-apigateway';

export class CdkWorkshopStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // defines an AWS Lambda resource
    const hello = new lambda.Function(this, 'HelloHandler', {
      runtime: lambda.Runtime.NODEJS_16_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'hello.handler'
    });
    
    // defines an API Gateway REST API resource backed by "hello" function.
    new apigw.LambdaRestApi(this, 'Endpoint', {
      handler: hello
    });
  }
}
```
Let's look at the differences in the stack.

```
cdk diff
```
You can see that a lot of resources are created at once, which shows the convenience of the CDK.

```
Resources
[+] AWS::ApiGateway::RestApi Endpoint EndpointEEF1FD8F 
[+] AWS::ApiGateway::Deployment Endpoint/Deployment EndpointDeployment318525DA5f8cdfe532107839d82cbce31f859259 
[+] AWS::ApiGateway::Stage Endpoint/DeploymentStage.prod EndpointDeploymentStageprodB78BEEA0 
[+] AWS::ApiGateway::Resource Endpoint/Default/{proxy+} Endpointproxy39E2174E 
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.CdkWorkshopStackEndpoint018E8349.ANY..{proxy+} EndpointproxyANYApiPermissionCdkWorkshopStackEndpoint018E8349ANYproxy747DCA52 
[+] AWS::Lambda::Permission Endpoint/Default/{proxy+}/ANY/ApiPermission.Test.CdkWorkshopStackEndpoint018E8349.ANY..{proxy+} EndpointproxyANYApiPermissionTestCdkWorkshopStackEndpoint018E8349ANYproxy41939001 
[+] AWS::ApiGateway::Method Endpoint/Default/{proxy+}/ANY EndpointproxyANYC09721C5 
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.CdkWorkshopStackEndpoint018E8349.ANY.. EndpointANYApiPermissionCdkWorkshopStackEndpoint018E8349ANYE84BEB04 
[+] AWS::Lambda::Permission Endpoint/Default/ANY/ApiPermission.Test.CdkWorkshopStackEndpoint018E8349.ANY.. EndpointANYApiPermissionTestCdkWorkshopStackEndpoint018E8349ANYB6CC1B64 
[+] AWS::ApiGateway::Method Endpoint/Default/ANY EndpointANY485C938B 
```
now, deploy it.

```
cdk deploy
```
You will see the following URL endpoints as output.

```
Outputs:
CdkWorkshopStack.Endpoint8024A810 = https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/
```
If you hit this endpoint with the crul command, you'll see the response come back from the Lambda function! You can also try it from your browser.

```
$ curl https://XXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/prod/
Hello, CDK! You've hit /
```

## Summary
This time, we created a simple backend app using CDK with API Gateway + Lambda configuration.
Compared to the case where you have to configure it in the console or by writing CloudFormation, it seems that you can complete the creation in a much shorter time. I would like to continue publishing the CDK series in the future.

Finally, if you want to delete the app you created this time, the following command will clean it up nicely.

```
cdk destroy
```

## Reference
https://cdkworkshop.com/20-typescript.html

Thank you!