Lambda\@Edge

Lambda@Edge 是 Amazon Web Services 提供的无服务器(serverless)平台。它允许你在 Amazon CloudFront 的边缘节点运行 Lambda 函数,从而可以自定义 HTTP 请求/响应的行为。

Hono 支持在 Node.js 18+ 环境下运行于 Lambda\@Edge。

1. 设置

在 Lambda\@Edge 上创建应用时,可以使用 CDK 来配置 CloudFront、IAM Role、API Gateway 等资源。

使用 cdk CLI 初始化项目。

npm

  1. mkdir my-app
  2. cd my-app
  3. cdk init app -l typescript
  4. npm i hono
  5. mkdir lambda

yarn

  1. mkdir my-app
  2. cd my-app
  3. cdk init app -l typescript
  4. yarn add hono
  5. mkdir lambda

pnpm

  1. mkdir my-app
  2. cd my-app
  3. cdk init app -l typescript
  4. pnpm add hono
  5. mkdir lambda

bun

  1. mkdir my-app
  2. cd my-app
  3. cdk init app -l typescript
  4. bun add hono
  5. mkdir lambda

2. Hello World

编辑 lambda/index_edge.ts

  1. import { Hono } from 'hono'
  2. import { handle } from 'hono/lambda-edge'
  3. const app = new Hono()
  4. app.get('/', (c) => c.text('Hello Hono on Lambda@Edge!'))
  5. export const handler = handle(app)

3. 部署

编辑 bin/my-app.ts

  1. #!/usr/bin/env node
  2. import 'source-map-support/register'
  3. import * as cdk from 'aws-cdk-lib'
  4. import { MyAppStack } from '../lib/my-app-stack'
  5. const app = new cdk.App()
  6. new MyAppStack(app, 'MyAppStack', {
  7. env: {
  8. account: process.env.CDK_DEFAULT_ACCOUNT,
  9. region: 'us-east-1',
  10. },
  11. })

编辑 lambda/cdk-stack.ts

  1. import { Construct } from 'constructs'
  2. import * as cdk from 'aws-cdk-lib'
  3. import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'
  4. import * as origins from 'aws-cdk-lib/aws-cloudfront-origins'
  5. import * as lambda from 'aws-cdk-lib/aws-lambda'
  6. import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'
  7. import * as s3 from 'aws-cdk-lib/aws-s3'
  8. export class MyAppStack extends cdk.Stack {
  9. public readonly edgeFn: lambda.Function
  10. constructor(scope: Construct, id: string, props?: cdk.StackProps) {
  11. super(scope, id, props)
  12. const edgeFn = new NodejsFunction(this, 'edgeViewer', {
  13. entry: 'lambda/index_edge.ts',
  14. handler: 'handler',
  15. runtime: lambda.Runtime.NODEJS_20_X,
  16. })
  17. // 上传任意 HTML 文件
  18. const originBucket = new s3.Bucket(this, 'originBucket')
  19. new cloudfront.Distribution(this, 'Cdn', {
  20. defaultBehavior: {
  21. origin: new origins.S3Origin(originBucket),
  22. edgeLambdas: [
  23. {
  24. functionVersion: edgeFn.currentVersion,
  25. eventType: cloudfront.LambdaEdgeEventType.VIEWER_REQUEST,
  26. },
  27. ],
  28. },
  29. })
  30. }
  31. }

最后运行以下命令进行部署:

  1. cdk deploy

Callback

如果你想添加 Basic Auth,并在验证后继续处理请求,可以使用 c.env.callback()

  1. import { Hono } from 'hono'
  2. import { basicAuth } from 'hono/basic-auth'
  3. import type { Callback, CloudFrontRequest } from 'hono/lambda-edge'
  4. import { handle } from 'hono/lambda-edge'
  5. type Bindings = {
  6. callback: Callback
  7. request: CloudFrontRequest
  8. }
  9. const app = new Hono<{ Bindings: Bindings }>()
  10. app.get(
  11. '*',
  12. basicAuth({
  13. username: 'hono',
  14. password: 'acoolproject',
  15. })
  16. )
  17. app.get('/', async (c, next) => {
  18. await next()
  19. c.env.callback(null, c.env.request)
  20. })
  21. export const handler = handle(app)