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 @@ -187,6 +187,17 @@ updates:
security:
applies-to: security-updates
patterns: ["*"]
- package-ecosystem: npm
directories: ["/examples/bun-hono/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/datadog/expressjs-streaming/cdk"
Expand Down
1 change: 1 addition & 0 deletions .github/example-matrix.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"image": [
{ "name": "bun-hono", "path": "/", "expect_body": "Hello from Hono" },
{ "name": "expressjs", "path": "/", "expect_body": "Hi there!" },
{ "name": "fastapi", "path": "/", "expect_body": "message" },
{ "name": "fastapi-background-tasks", "path": "/", "expect_body": "message" },
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ See the [FastAPI with SnapStart example](examples/fastapi-snapstart-zip) for a c
- [FastHTML with Response Streaming in Zip](examples/fasthtml-response-streaming-zip)
- [Remix](examples/remix/)
- [Remix in Zip](examples/remix-zip/)
- [Bun Hono](examples/bun-hono)
- [Sveltekit SSR Zip](examples/sveltekit-ssr-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 @@ -39,6 +39,7 @@ The repository includes working examples for many popular web frameworks, packag
| [SvelteKit SSR Zip](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/sveltekit-ssr-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 |
| [Bun Hono](https://github.com/aws/aws-lambda-web-adapter/tree/main/examples/bun-hono) | Docker | No |

## Java

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

This example shows how to use Lambda Web Adapter to run a [Hono](https://hono.dev) application on [Bun](https://bun.sh) in a container image.

The application is a Bun HTTP server in TypeScript. Bun runs the `index.ts` file directly, thus the application has no build step. The application has no Lambda-specific code. You can run the same image on Lambda, on Amazon ECS, or on your computer.

The top level folder is an AWS SAM project. The `app` directory contains the application and its [Dockerfile](app/Dockerfile).

This line of the Dockerfile copies the Lambda Web Adapter binary into `/opt/extensions`. It is the only change that Lambda needs.

```dockerfile
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
```

The examples in this repository get their base images from Amazon ECR Public. Bun has no official image there. Thus the Dockerfile starts from the Node.js image and installs Bun with npm.

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

## Pre-requisites

Install and configure these tools.

* [AWS CLI](https://aws.amazon.com/cli/)
* [SAM CLI](https://github.com/aws/aws-sam-cli)
* [Docker](https://www.docker.com/products/docker-desktop)

## Deploy to Lambda

Go to the folder of this example. Use SAM CLI to build the container image.

```shell
sam build
```

Deploy the application to your AWS account. SAM CLI asks you for the deployment settings.

```shell
sam deploy --guided
```

When the deployment is complete, find the `BunHonoApi` output. Its value is the URL of the API Gateway endpoint. Send a request to that URL.

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

```json
{"message":"Hello from Hono on Bun!","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.

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

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

## Run the docker locally

You can run the same image without Lambda. Build the image and start a container.

```shell
docker build -t bun-hono app
docker run --rm -p 8000:8000 bun-hono
```

Then send a request from a second terminal.

```shell
curl http://localhost:8000/
```

## Clean up

Delete the stack when you do not need the example.

```shell
sam delete
```
1 change: 1 addition & 0 deletions examples/bun-hono/app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
15 changes: 15 additions & 0 deletions examples/bun-hono/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM public.ecr.aws/docker/library/node:22-slim
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:1.1.0 /lambda-adapter /opt/extensions/lambda-adapter
# Bun has no official image on Amazon ECR Public, so install it with npm.
RUN npm install --global bun@1.4.2
# Listen on 8000 (the app reads PORT) so it doesn't collide with SAM's Runtime
# Interface Emulator on 8080 during local testing.
ENV PORT=8000
# The Lambda file system is read-only, so turn off Bun's transpiler cache.
ENV BUN_RUNTIME_TRANSPILER_CACHE_PATH=0
EXPOSE 8000
WORKDIR /var/task
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --production
COPY index.ts ./
CMD ["bun", "run", "index.ts"]
26 changes: 26 additions & 0 deletions examples/bun-hono/app/bun.lock

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

33 changes: 33 additions & 0 deletions examples/bun-hono/app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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?: string) => (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 on Bun!',
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 = Bun.serve({ port, fetch: app.fetch })
console.log(`Hono app listening on port ${server.port}`)

// Lambda sends SIGTERM before it shuts down the execution environment.
process.on('SIGTERM', async () => {
await server.stop()
process.exit(0)
})
16 changes: 16 additions & 0 deletions examples/bun-hono/app/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "bun-hono",
"version": "1.0.0",
"description": "Hono on Bun example for AWS Lambda Web Adapter",
"private": true,
"type": "module",
"scripts": {
"start": "bun run index.ts"
},
"dependencies": {
"hono": "^4.13.13"
},
"devDependencies": {
"@types/bun": "^1.4.2"
}
}
11 changes: 11 additions & 0 deletions examples/bun-hono/app/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "Preserve",
"moduleResolution": "bundler",
"types": ["bun"],
"strict": true,
"skipLibCheck": true,
"noEmit": true
}
}
32 changes: 32 additions & 0 deletions examples/bun-hono/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
bun-hono

Sample SAM Template for bun-hono

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

Resources:
BunHonoFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
MemorySize: 512
Architectures:
- x86_64
Events:
HttpEvents:
Type: HttpApi
Metadata:
DockerTag: v1
DockerContext: ./app
Dockerfile: Dockerfile

Outputs:
BunHonoApi:
Description: "API Gateway endpoint URL for Bun Hono function"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/"