AWS Lambda
AWS Lambda 是 Amazon Web Services 提供的无服务器(serverless)平台。你可以在响应事件时运行代码,并且底层的计算资源会自动管理。
Hono 可以运行在 Node.js 18+ 环境的 AWS Lambda 上。
1. 设置
在 AWS Lambda 上创建应用时,可以使用 CDK 来设置函数、IAM Role、API Gateway 等资源。
使用 cdk CLI 初始化项目。
npm
mkdir my-appcd my-appcdk init app -l typescriptnpm i hononpm i -D esbuildmkdir lambdatouch lambda/index.ts
yarn
mkdir my-appcd my-appcdk init app -l typescriptyarn add honoyarn add -D esbuildmkdir lambdatouch lambda/index.ts
pnpm
mkdir my-appcd my-appcdk init app -l typescriptpnpm add honopnpm add -D esbuildmkdir lambdatouch lambda/index.ts
bun
mkdir my-appcd my-appcdk init app -l typescriptbun add honobun add -D esbuildmkdir lambdatouch lambda/index.ts
2. Hello World
编辑 lambda/index.ts:
import { Hono } from 'hono'import { handle } from 'hono/aws-lambda'const app = new Hono()app.get('/', (c) => c.text('Hello Hono!'))export const handler = handle(app)
3. 部署
编辑 lib/my-app-stack.ts:
import * as cdk from 'aws-cdk-lib'import { Construct } from 'constructs'import * as lambda from 'aws-cdk-lib/aws-lambda'import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'export class MyAppStack extends cdk.Stack {constructor(scope: Construct, id: string, props?: cdk.StackProps) {super(scope, id, props)const fn = new NodejsFunction(this, 'lambda', {entry: 'lambda/index.ts',handler: 'handler',runtime: lambda.Runtime.NODEJS_22_X,})const fnUrl = fn.addFunctionUrl({authType: lambda.FunctionUrlAuthType.NONE,})new cdk.CfnOutput(this, 'lambdaUrl', {value: fnUrl.url!})}}
最后执行命令进行部署:
cdk deploy
返回二进制数据
Hono 支持以响应形式返回二进制数据。在 Lambda 中,返回二进制数据时需要进行 base64 编码。一旦将 Content-Type 头设置为二进制类型,Hono 会自动将数据编码为 base64。
app.get('/binary', async (c) => {// ...c.status(200)c.header('Content-Type', 'image/png') // 表示返回二进制数据return c.body(buffer) // 支持 `ArrayBufferLike` 类型,自动编码为 base64})
访问 AWS Lambda 对象
在 Hono 中,你可以通过绑定 LambdaEvent 和 LambdaContext 类型并使用 c.env 来访问 AWS Lambda 的 Events 和 Context。
import { Hono } from 'hono'import type { LambdaEvent, LambdaContext } from 'hono/aws-lambda'import { handle } from 'hono/aws-lambda'type Bindings = {event: LambdaEventlambdaContext: LambdaContext}const app = new Hono<{ Bindings: Bindings }>()app.get('/aws-lambda-info/', (c) => {return c.json({isBase64Encoded: c.env.event.isBase64Encoded,awsRequestId: c.env.lambdaContext.awsRequestId,})})export const handler = handle(app)
访问 RequestContext
在 Hono 中,你可以通过绑定 LambdaEvent 类型并使用 c.env.event.requestContext 来访问 AWS Lambda 的请求上下文。
import { Hono } from 'hono'import type { LambdaEvent } from 'hono/aws-lambda'import { handle } from 'hono/aws-lambda'type Bindings = {event: LambdaEvent}const app = new Hono<{ Bindings: Bindings }>()app.get('/custom-context/', (c) => {const lambdaContext = c.env.event.requestContextreturn c.json(lambdaContext)})export const handler = handle(app)
v3.10.0 之前版本(已弃用)
在旧版本中,可以通过绑定 ApiGatewayRequestContext 类型并使用 c.env 来访问请求上下文。
import { Hono } from 'hono'import type { ApiGatewayRequestContext } from 'hono/aws-lambda'import { handle } from 'hono/aws-lambda'type Bindings = {requestContext: ApiGatewayRequestContext}const app = new Hono<{ Bindings: Bindings }>()app.get('/custom-context/', (c) => {const lambdaContext = c.env.requestContextreturn c.json(lambdaContext)})export const handler = handle(app)
Lambda 响应流(Streaming)
通过修改 AWS Lambda 的调用模式,可以实现 Streaming Response。
fn.addFunctionUrl({authType: lambda.FunctionUrlAuthType.NONE,+ invokeMode: lambda.InvokeMode.RESPONSE_STREAM,})
通常,实现流式响应需要使用 awslambda.streamifyResponse 向 NodeJS.WritableStream 写入数据。但使用 AWS Lambda Adaptor 后,你可以直接使用 Hono 的传统流式响应,只需使用 streamHandle 替代 handle。
import { Hono } from 'hono'import { streamHandle } from 'hono/aws-lambda'import { streamText } from 'hono/streaming'const app = new Hono()app.get('/stream', async (c) => {return streamText(c, async (stream) => {for (let i = 0; i < 3; i++) {await stream.writeln(`${i}`)await stream.sleep(1)}})})export const handler = streamHandle(app)
