AWS Lambda
AWS Lambda 是 Amazon Web Services 提供的無伺服器平台。您可以執行程式碼以響應事件,並自動管理底層的運算資源。
Hono 可以在 AWS Lambda 上使用 Node.js 18+ 環境運作。
1. 設定
在 AWS Lambda 上建立應用程式時,使用 CDK 來設定 IAM 角色、API Gateway 和其他功能會很有幫助。
使用 cdk
CLI 初始化您的專案。
sh
mkdir my-app
cd my-app
cdk init app -l typescript
npm i hono
mkdir lambda
touch lambda/index.ts
sh
mkdir my-app
cd my-app
cdk init app -l typescript
yarn add hono
mkdir lambda
touch lambda/index.ts
sh
mkdir my-app
cd my-app
cdk init app -l typescript
pnpm add hono
mkdir lambda
touch lambda/index.ts
sh
mkdir my-app
cd my-app
cdk init app -l typescript
bun add hono
mkdir lambda
touch lambda/index.ts
2. Hello World
編輯 lambda/index.ts
。
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/cdk-stack.ts
。
ts
import * as cdk from 'aws-cdk-lib'
import { Construct } from 'constructs'
import * as lambda from 'aws-cdk-lib/aws-lambda'
import * as apigw from 'aws-cdk-lib/aws-apigateway'
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_20_X,
})
fn.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
})
new apigw.LambdaRestApi(this, 'myapi', {
handler: fn,
})
}
}
最後,執行命令進行部署
sh
cdk deploy
提供二進位資料
Hono 支援以二進位資料作為回應。在 Lambda 中,需要 base64 編碼才能返回二進位資料。一旦二進位類型設定為 Content-Type
標頭,Hono 會自動將資料編碼為 base64。
ts
app.get('/binary', async (c) => {
// ...
c.status(200)
c.header('Content-Type', 'image/png') // means binary data
return c.body(buffer) // supports `ArrayBufferLike` type, encoded to base64.
})
存取 AWS Lambda 物件
在 Hono 中,您可以透過綁定 LambdaEvent
、LambdaContext
類型並使用 c.env
來存取 AWS Lambda 事件和上下文。
ts
import { Hono } from 'hono'
import type { LambdaEvent, LambdaContext } from 'hono/aws-lambda'
import { handle } from 'hono/aws-lambda'
type Bindings = {
event: LambdaEvent
lambdaContext: 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 請求上下文。
ts
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.requestContext
return c.json(lambdaContext)
})
export const handler = handle(app)
v3.10.0 之前的版本(已棄用)
您可以透過綁定 ApiGatewayRequestContext
類型並使用 c.env.
來存取 AWS Lambda 請求上下文。
ts
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.requestContext
return c.json(lambdaContext)
})
export const handler = handle(app)
Lambda 回應串流
透過變更 AWS Lambda 的調用模式,您可以實現串流回應。
差異
fn.addFunctionUrl({
authType: lambda.FunctionUrlAuthType.NONE,
+ invokeMode: lambda.InvokeMode.RESPONSE_STREAM,
})
通常,實作需要使用 awslambda.streamifyResponse 將區塊寫入 NodeJS.WritableStream,但使用 AWS Lambda 適配器,您可以透過使用 streamHandle 而非 handle 來實現 Hono 的傳統串流回應。
ts
import { Hono } from 'hono'
import { streamHandle } from 'hono/aws-lambda'
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)
}
})
})
const handler = streamHandle(app)