I published a post this summer with a few simple demo applications I use when configuring AWS infrastructure. I needed something similar for a serverless application on AWS. In other words, a Lambda function sitting behind an API Gateway or Application Load Balancer (ALB).
I tend to use this simple Node.js function. It will return whatever it received as input. This is useful when you are debugging the infrastructure. For example, configuring Cognito with API Gateway or OIDC with ALB.
1
2
3
4
5
6
7
8
9
10
|
exports.handler = async (event, context) => {
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"isBase64Encoded": false,
"body": JSON.stringify(event)
};
};
|
Deploying this as a serverless function behind an API Gateway REST API is really easy. Here is a SAM template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
SimpleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs14.x
Timeout: 300
Events:
ApiEvent:
Type: Api
Properties:
Method: get
Path: /
InlineCode: |
exports.handler = async (event, context) => {
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"isBase64Encoded": false,
"body": JSON.stringify(event)
};
};
|
Deploying an HTTP API is nearly identical. I simply change ApiEvent to HttpApiEvent.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
SimpleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs14.x
Timeout: 300
Events:
HttpApiEvent:
Type: HttpApi
Properties:
Path: /
Method: GET
InlineCode: |
exports.handler = async (event, context) => {
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"isBase64Encoded": false,
"body": JSON.stringify(event)
};
};
|
The Application Load Balancer is a little more complicated. First, SAM templates don’t support ALB as a event source. Second, the ALB requires you specify subnets and a security group. I use the following template.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Parameters:
Subnets:
Description: Subnets the Application Load Balancer should be deployed in
Type: List<AWS::EC2::Subnet::Id>
SecurityGroup:
Description: Security Group applied to the Application Load Balancer
Type: AWS::EC2::SecurityGroup::Id
Resources:
SimpleFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs14.x
Timeout: 300
InlineCode: |
exports.handler = async (event, context) => {
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"isBase64Encoded": false,
"body": JSON.stringify(event)
};
};
LoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Subnets: !Ref Subnets
SecurityGroups:
- !Ref SecurityGroup
LoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
LoadBalancerArn: !Ref LoadBalancer
Port: 80
Protocol: HTTP
DefaultActions:
- Type: forward
TargetGroupArn: !Ref LoadBalancerTargetGroup
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt [ SimpleFunction, Arn ]
Action: 'lambda:InvokeFunction'
Principal: elasticloadbalancing.amazonaws.com
LoadBalancerTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: false
TargetType: lambda
Targets:
- Id: !GetAtt [ SimpleFunction, Arn ]
|