Skip to content

Commit 1e8dee7

Browse files
authored
Add SQS-Expressjs example (awslabs#347)
* Add SQS-Expressjs example * Update Dockerfile
1 parent 82e5ade commit 1e8dee7

File tree

9 files changed

+1263
-13
lines changed

9 files changed

+1263
-13
lines changed

README.md

+14-13
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,18 @@ After passing readiness check, Lambda Web Adapter will start Lambda Runtime and
8989

9090
The readiness check port/path and traffic port can be configured using environment variables. These environment variables can be defined either within docker file or as Lambda function configuration.
9191

92-
| Environment Variable | Description | Default |
93-
|--------------------------------------------------------------|-------------------------------------------------------------------------------------|------------|
94-
| AWS_LWA_PORT / PORT* | traffic port | "8080" |
95-
| AWS_LWA_READINESS_CHECK_PORT / READINESS_CHECK_PORT* | readiness check port, default to the traffic port | PORT |
96-
| AWS_LWA_READINESS_CHECK_PATH / READINESS_CHECK_PATH* | readiness check path | "/" |
97-
| AWS_LWA_READINESS_CHECK_PROTOCOL / READINESS_CHECK_PROTOCOL* | readiness check protocol: "http" or "tcp", default is "http" | "http" |
98-
| AWS_LWA_READINESS_CHECK_MIN_UNHEALTHY_STATUS | The minimum HTTP status code that is considered unhealthy | "500" |
99-
| AWS_LWA_ASYNC_INIT / ASYNC_INIT* | enable asynchronous initialization for long initialization functions | "false" |
100-
| AWS_LWA_REMOVE_BASE_PATH / REMOVE_BASE_PATH* | the base path to be removed from request path | None |
101-
| AWS_LWA_ENABLE_COMPRESSION | enable gzip compression for response body | "false" |
102-
| AWS_LWA_INVOKE_MODE | Lambda function invoke mode: "buffered" or "response_stream", default is "buffered" | "buffered" |
103-
| AWS_LWA_PASS_THROUGH_PATH | Path to receive events payloads passed through from non-http event triggers | "/events" |
92+
| Environment Variable | Description | Default |
93+
|--------------------------------------------------------------|--------------------------------------------------------------------------------------|------------|
94+
| AWS_LWA_PORT / PORT* | traffic port | "8080" |
95+
| AWS_LWA_READINESS_CHECK_PORT / READINESS_CHECK_PORT* | readiness check port, default to the traffic port | PORT |
96+
| AWS_LWA_READINESS_CHECK_PATH / READINESS_CHECK_PATH* | readiness check path | "/" |
97+
| AWS_LWA_READINESS_CHECK_PROTOCOL / READINESS_CHECK_PROTOCOL* | readiness check protocol: "http" or "tcp", default is "http" | "http" |
98+
| AWS_LWA_READINESS_CHECK_MIN_UNHEALTHY_STATUS | The minimum HTTP status code that is considered unhealthy | "500" |
99+
| AWS_LWA_ASYNC_INIT / ASYNC_INIT* | enable asynchronous initialization for long initialization functions | "false" |
100+
| AWS_LWA_REMOVE_BASE_PATH / REMOVE_BASE_PATH* | the base path to be removed from request path | None |
101+
| AWS_LWA_ENABLE_COMPRESSION | enable gzip compression for response body | "false" |
102+
| AWS_LWA_INVOKE_MODE | Lambda function invoke mode: "buffered" or "response_stream", default is "buffered" | "buffered" |
103+
| AWS_LWA_PASS_THROUGH_PATH | the path for receiving event payloads that are passed through from non-http triggers | "/events" |
104104

105105
> **Note:**
106106
> We use "AWS_LWA_" prefix to namespacing all environment variables used by Lambda Web Adapter. The original ones will be supported until we reach version 1.0.
@@ -161,7 +161,7 @@ Please note that `sam local` starts a Lambda Runtime Interface Emulator on port
161161

162162
## Non-HTTP Event Triggers
163163

164-
Lambda Web Adapter supports non-http event triggers (such as SQS, EventBridge, and Bedrock Agents, etc.). The adapter will forward the event payload to the web application at the path specified by environment variable `AWS_LWA_PASS_THROUGH_PATH`. The default path is `/events`. The web application can retrieve the event payload from the request body. The http response body must be a valid JSON string and will be passed back as the response payload to the Lambda service.
164+
The Lambda Web Adapter also supports all non-HTTP event triggers, such as SQS, SNS, S3, DynamoDB, Kinesis, Kafka, EventBridge, and Bedrock Agents. The adapter forwards the event payload to the web application via a path defined by the `AWS_LWA_PASS_THROUGH_PATH` environment variable. By default, this path is set to `/events`. Upon receiving the event payload from the request body, the web application should processes it and returns the results as a JSON response. Please checkout [SQS Express.js](examples/sqs-expressjs) on how to use it.
165165

166166
## Examples
167167

@@ -191,6 +191,7 @@ Lambda Web Adapter supports non-http event triggers (such as SQS, EventBridge, a
191191
- [ASP.NET MVC](examples/aspnet-mvc)
192192
- [ASP.NET MVC in Zip](examples/aspnet-mvc-zip)
193193
- [ASP.NET Web API in Zip](examples/aspnet-webapi-zip)
194+
- [SQS Express.js](examples/sqs-expressjs)
194195

195196
## Acknowledgement
196197

examples/sqs-expressjs/.gitignore

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
HELP.md
2+
target/
3+
4+
### IntelliJ IDEA ###
5+
.idea
6+
*.iws
7+
*.iml
8+
*.ipr
9+
10+
### VS Code ###
11+
.vscode/
12+
13+
.aws-sam
14+
node_modules

examples/sqs-expressjs/README.md

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# SQS Express.js example
2+
3+
This project demonstrates the integration of Amazon Simple Queue Service (SQS) with an Express.js application. It showcases how to effectively manage and process messages from an SQS queue within an Express.js application environment.
4+
5+
In this Express.js application integrated with Amazon SQS, there is no explicit code required to poll the SQS queue. The AWS Lambda handles the polling of the SQS queue and Lambda Web Adapter forwards the event payload to the Express.js application. This simplifies the application code and allows developers to focus on processing the event payload rather than managing the queue polling logic.
6+
7+
The application can be deployed in an AWS account using the [Serverless Application Model](https://github.com/awslabs/serverless-application-model). The `template.yaml` file in the root folder contains the application definition.
8+
9+
The top level folder is a typical AWS SAM project. The `app` directory is an express.js application with a [Dockerfile](app/Dockerfile).
10+
11+
```dockerfile
12+
FROM public.ecr.aws/docker/library/node:20-slim
13+
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.0 /lambda-adapter /opt/extensions/lambda-adapter
14+
ENV PORT=8000 AWS_LWA_READINESS_CHECK_PROTOCOL=tcp
15+
WORKDIR "/var/task"
16+
ADD src/package.json /var/task/package.json
17+
ADD src/package-lock.json /var/task/package-lock.json
18+
RUN npm install --omit=dev
19+
ADD src/ /var/task
20+
CMD ["node", "index.js"]
21+
```
22+
23+
Line 2 copies lambda adapter binary into /opt/extenions. This is the only change to run the express.js application on Lambda.
24+
25+
```dockerfile
26+
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.0 /lambda-adapter /opt/extensions/lambda-adapter
27+
```
28+
29+
## Pre-requisites
30+
31+
The following tools should be installed and configured.
32+
33+
* [AWS CLI](https://aws.amazon.com/cli/)
34+
* [SAM CLI](https://github.com/awslabs/aws-sam-cli)
35+
* [Node](https://nodejs.org/en/)
36+
* [Docker](https://www.docker.com/products/docker-desktop)
37+
38+
## Build
39+
40+
Navigate to the sample's folder and use the SAM CLI to build a container image
41+
42+
```shell
43+
sam build
44+
```
45+
## Deploy
46+
47+
This command compiles the application and prepares a deployment package in the `.aws-sam` sub-directory.
48+
49+
To deploy the application in your AWS account, you can use the SAM CLI's guided deployment process and follow the instructions on the screen
50+
51+
```shell
52+
sam deploy --guided
53+
```
54+
55+
Please take note of the container image name.
56+
Once the deployment is completed, the SAM CLI will print out the stack's outputs, including the new sqs queue URL.
57+
58+
```shell
59+
...
60+
---------------------------------------------------------------------------------------------------------------------------------------
61+
Outputs
62+
---------------------------------------------------------------------------------------------------------------------------------------
63+
Key SqsQueueUrl
64+
Description SQS URL the express Lambda Function will receive messages from
65+
Value https://sqs.us-west-2.amazonaws.com/xxxxxxxx/xxxxxxxx
66+
---------------------------------------------------------------------------------------------------------------------------------------
67+
68+
```
69+
70+
## Test
71+
72+
Use the following command to send a message to the sqs queue.
73+
74+
```shell
75+
aws sqs send-message --queue-url <replace with your sqs queue url> --message-body "Hello from CLI"
76+
```
77+
78+
Run the following command to see the Lambda function's CloudWatch logs.
79+
80+
```shell
81+
sam logs --tail --stack-name <replace with your stack name>
82+
```
83+
84+
## Local Test
85+
86+
You can also use SAM CLI for local testing.
87+
88+
```shell
89+
sam local invoke SqsExpressFunction -e events/sqs.json
90+
```
91+
92+
Here is a sample output from this command.
93+
94+
```shell
95+
Invoking Container created from sqsexpressfunction:v1
96+
Building image.................
97+
Using local image: sqsexpressfunction:rapid-x86_64.
98+
99+
START RequestId: ceaaf9bb-8d8c-42a5-828c-a5d4c8a506f1 Version: $LATEST
100+
Example app listening at http://localhost:8000
101+
Received event: {"Records":[{"messageId":"19dd0b57-b21e-4ac1-bd88-01bbb068cb78","receiptHandle":"MessageReceiptHandle","body":"Hello from SQS!","attributes":{"ApproximateReceiveCount":"1","SentTimestamp":"1523232000000","SenderId":"123456789012","ApproximateFirstReceiveTimestamp":"1523232000001"},"messageAttributes":{},"md5OfBody":"7b270e59b47ff90a553787216d55d91d","eventSource":"aws:sqs","eventSourceARN":"arn:aws:sqs:us-east-1:123456789012:MyQueue","awsRegion":"us-east-1"}]}
102+
processing message: 19dd0b57-b21e-4ac1-bd88-01bbb068cb78 with body: Hello from SQS!
103+
END RequestId: ceaaf9bb-8d8c-42a5-828c-a5d4c8a506f1
104+
REPORT RequestId: ceaaf9bb-8d8c-42a5-828c-a5d4c8a506f1 Init Duration: 0.10 ms Duration: 117.12 ms Billed Duration: 118 ms Memory Size: 1024 MB Max Memory Used: 1024 MB
105+
"success"
106+
```

examples/sqs-expressjs/app/Dockerfile

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM public.ecr.aws/docker/library/node:20-slim
2+
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.0 /lambda-adapter /opt/extensions/lambda-adapter
3+
ENV PORT=8000 AWS_LWA_READINESS_CHECK_PROTOCOL=tcp
4+
WORKDIR "/var/task"
5+
ADD src/package.json /var/task/package.json
6+
ADD src/package-lock.json /var/task/package-lock.json
7+
RUN npm install --omit=dev
8+
ADD src/ /var/task
9+
CMD ["node", "index.js"]
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const express = require('express')
2+
const bodyParser = require('body-parser')
3+
4+
const app = express()
5+
const port = process.env['PORT'] || 8080
6+
7+
// setup bodyParser to parse application/json
8+
app.use(bodyParser.json())
9+
10+
11+
// LWA sends SQS messages to this endpoint, use environment variable 'AWS_LWA_PASS_THROUGH_PATH' to configure this path
12+
app.post('/events', (req, res) => {
13+
console.log(`Received event: ${JSON.stringify(req.body)}`)
14+
15+
// printout the message Id and body
16+
req.body.Records.forEach((record) => {
17+
console.log(`processing message: ${record.messageId} with body: ${record.body}`)
18+
})
19+
20+
// send a 200 response with json string 'success'
21+
res.json('success')
22+
})
23+
24+
app.listen(port, () => {
25+
console.log(`Example app listening at http://localhost:${port}`)
26+
})

0 commit comments

Comments
 (0)