Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,17 @@ updates:
security:
applies-to: security-updates
patterns: ["*"]
- package-ecosystem: npm
directories: ["/examples/hono-zip/app"]
schedule:
interval: weekly
open-pull-requests-limit: 0
commit-message:
prefix: chore
groups:
security:
applies-to: security-updates
patterns: ["*"]
- package-ecosystem: npm
directories: ["/examples/nextjs/app"]
schedule:
Expand Down
1 change: 1 addition & 0 deletions .github/example-matrix.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{ "name": "fasthtml-zip", "path": "/", "expect_body": "Hello World", "port": "8000" },
{ "name": "flask-zip", "path": "/", "expect_body": "message", "port": "8000" },
{ "name": "gin-zip", "path": "/", "expect_body": "message", "port": "8000" },
{ "name": "hono-zip", "path": "/", "expect_body": "Hello from Hono", "port": "8000" },
{ "name": "remix-zip", "path": "/", "expect_body": "Welcome to", "port": "8000" },
{ "name": "springboot-zip", "path": "/v1/", "expect_body": "Hello, world!", "port": "8000" }
],
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ See the [FastAPI with SnapStart example](examples/fastapi-snapstart-zip) for a c
- [Remix](examples/remix/)
- [Remix in Zip](examples/remix-zip/)
- [Sveltekit SSR Zip](examples/sveltekit-ssr-zip/)
- [Hono in Zip](examples/hono-zip)
- [Datadog](examples/datadog)
- [Datadog in Zip](examples/datadog-zip)

Expand Down
1 change: 1 addition & 0 deletions docs/guide/src/examples/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ The repository includes working examples for many popular web frameworks, packag
| [Remix](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/remix) | Docker | No |
| [Remix in Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/remix-zip) | Zip | No |
| [SvelteKit SSR Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/sveltekit-ssr-zip) | Zip | No |
| [Hono in Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/hono-zip) | Zip | No |
| [Bun GraphQL](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/bun-graphql-zip) | Zip | No |
| [Bun GraphQL Streaming](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/bun-graphql-streaming-zip) | Zip | Yes |

Expand Down
2 changes: 2 additions & 0 deletions examples/hono-zip/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.aws-sam
80 changes: 80 additions & 0 deletions examples/hono-zip/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# hono-zip

This example shows how to use Lambda Web Adapter to run a [Hono](https://hono.dev) application on the managed Node.js runtime.

The application is a Node.js HTTP server. It uses [@hono/node-server](https://github.com/honojs/node-server) to start the server, and it has no Lambda-specific code. Thus you can run the same `index.js` file on Lambda, in a container, or on your computer.

### How does it work?

Add the Lambda Web Adapter layer to the function and configure the wrapper script.

1. Attach the Lambda Web Adapter layer to the function. The layer contains the Lambda Web Adapter binary and a wrapper script.
1. x86_64: `arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerX86:30`
2. arm64: `arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerArm64:30`
2. Set the Lambda environment variable `AWS_LAMBDA_EXEC_WRAPPER` to `/opt/bootstrap`. This is the wrapper script in the layer.
3. Set the function handler to the startup command `run.sh`. The wrapper script runs this command to start the application.

The application listens on the port that the `PORT` environment variable gives. Lambda Web Adapter uses the same variable to find the application.

For more information about wrapper scripts, refer to the [Lambda documentation](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-modify.html#runtime-wrapper).

### Build and Deploy

Run these commands to build the application and deploy it to Lambda.

```bash
sam build
sam deploy --guided
```

When the deployment is complete, find the `HonoApi` output. Its value is the URL of the API Gateway endpoint.

### Verify it works

Send a request to the `HonoApi` URL.

```bash
curl https://<api-id>.execute-api.<region>.amazonaws.com/
```

```json
{"message":"Hello from Hono!","requestId":"<request-id>","functionName":"<function-name>"}
```

Lambda Web Adapter sends the request context from API Gateway and the Lambda context to the application. It puts them in the `x-amzn-request-context` and `x-amzn-lambda-context` headers. The application reads the request ID from the first header and the function name from the second header.

The two contexts contain your AWS account ID. Thus the application does not return the full contexts.

The application also has a route with a path parameter.

```bash
curl https://<api-id>.execute-api.<region>.amazonaws.com/hello/lambda
```

```json
{"message":"Hello, lambda!"}
```

### Run it locally

You can run the application without Lambda.

```bash
cd app
npm install
PORT=8000 npm start
```

Then send a request from a second terminal.

```bash
curl http://localhost:8000/
```

### Clean up

Delete the stack when you do not need the example.

```bash
sam delete
```
34 changes: 34 additions & 0 deletions examples/hono-zip/app/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { serve } from '@hono/node-server'
import { Hono } from 'hono'

const app = new Hono()
const port = Number(process.env.PORT || 8080)

// Lambda Web Adapter forwards the API Gateway request context and the Lambda
// context to the app as JSON strings in two HTTP headers.
const parseContext = (header) => (header ? JSON.parse(header) : null)

app.get('/', (c) => {
const requestContext = parseContext(c.req.header('x-amzn-request-context'))
const lambdaContext = parseContext(c.req.header('x-amzn-lambda-context'))

// Return two fields only. The full contexts contain the AWS account ID.
return c.json({
message: 'Hello from Hono!',
requestId: requestContext?.requestId ?? null,
functionName: lambdaContext?.env_config?.function_name ?? null,
})
})

app.get('/hello/:name', (c) => {
return c.json({ message: `Hello, ${c.req.param('name')}!` })
})

const server = serve({ fetch: app.fetch, port }, (info) => {
console.log(`Hono app listening on port ${info.port}`)
})

// Lambda sends SIGTERM before it shuts down the execution environment.
process.on('SIGTERM', () => {
server.close(() => process.exit(0))
})
37 changes: 37 additions & 0 deletions examples/hono-zip/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions examples/hono-zip/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "hono-zip",
"version": "1.0.0",
"description": "Hono example for AWS Lambda Web Adapter",
"private": true,
"type": "module",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@hono/node-server": "^2.1.4",
"hono": "^4.13.13"
}
}
3 changes: 3 additions & 0 deletions examples/hono-zip/app/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

exec node index.js
44 changes: 44 additions & 0 deletions examples/hono-zip/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hono-zip

Sample SAM Template for hono-zip

# More info about Globals: https://github.com/aws/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 10

Resources:
HonoFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/aws/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: app/
Handler: run.sh
Runtime: nodejs22.x
MemorySize: 512
Architectures:
- x86_64
Environment:
Variables:
AWS_LAMBDA_EXEC_WRAPPER: /opt/bootstrap
# Listen on 8000 so the app doesn't collide with SAM's Runtime
# Interface Emulator on 8080 during local testing.
PORT: 8000
Layers:
- !Sub arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerX86:30
Events:
HttpEvents:
Type: HttpApi

Outputs:
HonoApi:
Description: "API Gateway endpoint URL for Hono function"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/"
HonoFunction:
Description: "Hono Lambda Function ARN"
Value: !GetAtt HonoFunction.Arn
HonoFunctionIamRole:
Description: "Implicit IAM Role created for Hono function"
Value: !GetAtt HonoFunctionRole.Arn