Add hummingbird Lambda example (#544)

Add Hummingbird web framework integration example for AWS Lambda

**Motivation:**
Developers using the Hummingbird web framework need a clear example of
how to integrate it with AWS Lambda. The existing examples focus on
basic Lambda handlers, but don't demonstrate how to use popular Swift
web frameworks like Hummingbird in a serverless context.

**Modifications:**
Added a complete Hummingbird Lambda example in Examples/Hummingbird/
including Package.swift with Hummingbird Lambda dependencies, main.swift
demonstrating router setup with API Gateway V2 integration, SAM template
for deployment, and comprehensive README documentation with build,
deploy, and usage instructions.

**Result:**
Developers can now easily create AWS Lambda functions using the
Hummingbird web framework, with a working example that shows router
configuration, API Gateway integration, and complete deployment workflow
using familiar Hummingbird syntax.
This commit is contained in:
Sébastien Stormacq
2025-08-05 15:13:13 +02:00
committed by GitHub
parent 447c1e4db1
commit a5ff8e5c00
7 changed files with 209 additions and 1 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
# We pass the list of examples here, but we can't pass an array as argument
# Instead, we pass a String with a valid JSON array.
# The workaround is mentioned here https://github.com/orgs/community/discussions/11692
examples: "[ 'APIGateway', 'APIGateway+LambdaAuthorizer', 'BackgroundTasks', 'HelloJSON', 'HelloWorld', 'ResourcesPackaging', 'S3EventNotifier', 'S3_AWSSDK', 'S3_Soto', 'Streaming', 'StreamingFromEvent', 'ServiceLifecycle+Postgres', 'Testing', 'Tutorial' ]"
examples: "[ 'APIGateway', 'APIGateway+LambdaAuthorizer', 'BackgroundTasks', 'HelloJSON', 'HelloWorld', 'HummingbirdLambda', 'ResourcesPackaging', 'S3EventNotifier', 'S3_AWSSDK', 'S3_Soto', 'Streaming', 'StreamingFromEvent', 'ServiceLifecycle+Postgres', 'Testing', 'Tutorial' ]"
archive_plugin_examples: "[ 'HelloWorld', 'ResourcesPackaging' ]"
archive_plugin_enabled: true
+9
View File
@@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
samconfig.toml
+59
View File
@@ -0,0 +1,59 @@
// swift-tools-version: 6.1
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
// needed for CI to test the local version of the library
import struct Foundation.URL
let package = Package(
name: "HBLambda",
platforms: [.macOS(.v15)],
dependencies: [
.package(
url: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
from: "2.0.0-beta.1"
),
.package(
url: "https://github.com/hummingbird-project/hummingbird-lambda.git",
branch: "main"
),
.package(url: "https://github.com/swift-server/swift-aws-lambda-events.git", from: "1.1.0"),
],
targets: [
.executableTarget(
name: "HBLambda",
dependencies: [
.product(name: "HummingbirdLambda", package: "hummingbird-lambda"),
.product(name: "AWSLambdaEvents", package: "swift-aws-lambda-events"),
]
)
]
)
if let localDepsPath = Context.environment["LAMBDA_USE_LOCAL_DEPS"],
localDepsPath != "",
let v = try? URL(fileURLWithPath: localDepsPath).resourceValues(forKeys: [.isDirectoryKey]),
v.isDirectory == true
{
// when we use the local runtime as deps, let's remove the dependency added above
let indexToRemove = package.dependencies.firstIndex { dependency in
if case .sourceControl(
name: _,
location: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
requirement: _
) = dependency.kind {
return true
}
return false
}
if let indexToRemove {
package.dependencies.remove(at: indexToRemove)
}
// then we add the dependency on LAMBDA_USE_LOCAL_DEPS' path (typically ../..)
print("[INFO] Compiling against swift-aws-lambda-runtime located at \(localDepsPath)")
package.dependencies += [
.package(name: "swift-aws-lambda-runtime", path: localDepsPath)
]
}
+80
View File
@@ -0,0 +1,80 @@
# Hummingbird Lambda
This is a simple example of an AWS Lambda function using the [Hummingbird](https://github.com/hummingbird-project/hummingbird) web framework, invoked through an Amazon API Gateway.
## Code
The Lambda function uses Hummingbird's router to handle HTTP requests. It defines a simple GET endpoint at `/hello` that returns "Hello".
The code creates a `Router` with `AppRequestContext` (which is a type alias for `BasicLambdaRequestContext<APIGatewayV2Request>`). The router defines HTTP routes using Hummingbird's familiar syntax.
The `APIGatewayV2LambdaFunction` wraps the Hummingbird router to make it compatible with AWS Lambda and API Gateway V2 events.
`APIGatewayV2Request` is defined in the [Swift AWS Lambda Events](https://github.com/swift-server/swift-aws-lambda-events) library, and the Hummingbird Lambda integration is provided by the [Hummingbird Lambda](https://github.com/hummingbird-project/hummingbird-lambda) package.
## Build & Package
To build the package, type the following commands.
```bash
swift build
swift package archive --allow-network-connections docker
```
If there is no error, there is a ZIP file ready to deploy.
The ZIP file is located at `.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/HBLambda/HBLambda.zip`
## Deploy
The deployment must include the Lambda function and the API Gateway. We use the [Serverless Application Model (SAM)](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) to deploy the infrastructure.
**Prerequisites** : Install the [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html)
The example directory contains a file named `template.yaml` that describes the deployment.
To actually deploy your Lambda function and create the infrastructure, type the following `sam` command.
```bash
sam deploy \
--resolve-s3 \
--template-file template.yaml \
--stack-name HummingbirdLambda \
--capabilities CAPABILITY_IAM
```
At the end of the deployment, the script lists the API Gateway endpoint.
The output is similar to this one.
```
-----------------------------------------------------------------------------------------------------------------------------
Outputs
-----------------------------------------------------------------------------------------------------------------------------
Key APIGatewayEndpoint
Description API Gateway endpoint URL"
Value https://a5q74es3k2.execute-api.us-east-1.amazonaws.com
-----------------------------------------------------------------------------------------------------------------------------
```
## Invoke your Lambda function
To invoke the Lambda function, use this `curl` command line to call the `/hello` endpoint.
```bash
curl https://a5q74es3k2.execute-api.us-east-1.amazonaws.com/hello
```
Be sure to replace the URL with the API Gateway endpoint returned in the previous step.
This should print:
```bash
Hello
```
## Undeploy
When done testing, you can delete the infrastructure with this command.
```bash
sam delete
```
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftAWSLambdaRuntime open source project
//
// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import AWSLambdaEvents
import HummingbirdLambda
import Logging
typealias AppRequestContext = BasicLambdaRequestContext<APIGatewayV2Request>
let router = Router(context: AppRequestContext.self)
router.get("hello") { _, _ in
"Hello"
}
let lambda = APIGatewayV2LambdaFunction(router: router)
try await lambda.runService()
+31
View File
@@ -0,0 +1,31 @@
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Hummingbird Lambda Example
Resources:
# Lambda function
HBLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: .build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/HBLambda/HBLambda.zip
Timeout: 60
Handler: swift.bootstrap # ignored by the Swift runtime
Runtime: provided.al2
MemorySize: 512
Architectures:
- arm64
Environment:
Variables:
# by default, AWS Lambda runtime produces no log
# use `LOG_LEVEL: debug` for for lifecycle and event handling information
# use `LOG_LEVEL: trace` for detailed input event information
LOG_LEVEL: debug
Events:
HttpApiEvent:
Type: HttpApi
Outputs:
# print API Gateway endpoint
APIGatewayEndpoint:
Description: API Gateway endpoint URI"
Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com"
+2
View File
@@ -28,6 +28,8 @@ This directory contains example code for Lambda functions.
- **[HelloWorld](HelloWorld/README.md)**: a simple Lambda function (requires [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)).
- **[Hummingbird](Hummingbird/README.md)**: a Lambda function using the Hummingbird web framework with API Gateway integration (requires [AWS SAM](https://aws.amazon.com/serverless/sam/)).
- **[S3EventNotifier](S3EventNotifier/README.md)**: a Lambda function that receives object-upload notifications from an [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) bucket.
- **[S3_AWSSDK](S3_AWSSDK/README.md)**: a Lambda function that uses the [AWS SDK for Swift](https://docs.aws.amazon.com/sdk-for-swift/latest/developer-guide/getting-started.html) to invoke an [Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html) API (requires [AWS SAM](https://aws.amazon.com/serverless/sam/)).