From 307d2483b0f3ccd67874afef27d5fe828eb60170 Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Thu, 14 May 2026 11:13:46 +0200 Subject: [PATCH 1/3] add readme for resource example --- Examples/README.md | 2 + Examples/ResourcesPackaging/README.md | 113 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 Examples/ResourcesPackaging/README.md diff --git a/Examples/README.md b/Examples/README.md index 2096c0adc..725f6c88c 100644 --- a/Examples/README.md +++ b/Examples/README.md @@ -32,6 +32,8 @@ This directory contains example code for Lambda functions. - **[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/)). +- **[ResourcesPackaging](ResourcesPackaging/README.md)**: a Lambda function that demonstrates how to bundle and read static resource files using Swift Package Manager's resource bundling feature (requires [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)). + - **[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/)). diff --git a/Examples/ResourcesPackaging/README.md b/Examples/ResourcesPackaging/README.md new file mode 100644 index 000000000..2911ba20c --- /dev/null +++ b/Examples/ResourcesPackaging/README.md @@ -0,0 +1,113 @@ +# Resources Packaging + +This is an example of an AWS Lambda function that reads a bundled resource file and returns its content as a response. + +This example demonstrates how to include static resources (such as text files, configuration files, or templates) in your Lambda function package using Swift Package Manager's resource bundling feature. + +## Code + +The code creates a `LambdaRuntime` struct with a handler that reads a bundled text file and returns its content. + +The handler is `(event: String, context: LambdaContext)`. The function takes two arguments: +- the event argument is a `String`. It is the parameter passed when invoking the function. +- the context argument is a `Lambda Context`. It is a description of the runtime context. + +The handler uses `Bundle.module.url(forResource:withExtension:)` to locate the `hello.txt` file that was bundled with the executable at build time. It then reads the file content and returns it as the function response. + +The `Package.swift` file declares the resource using the `.process("hello.txt")` directive, which tells Swift Package Manager to include the file in the module's resource bundle. + +## Test locally + +You can test your function locally before deploying it to AWS Lambda. + +To start the local function, type the following commands: + +```bash +swift run +``` + +It will compile your code and start the local server. You know the local server is ready to accept connections when you see this message. + +```txt +Building for debugging... +Build of product 'MyLambda' complete! (0.31s) +2025-01-29T12:44:48+0100 info LocalServer : host="127.0.0.1" port=7000 [AWSLambdaRuntime] Server started and listening +``` + +Then, from another Terminal, send your payload with `curl`. + +```bash +curl -d '"hello"' http://127.0.0.1:7000/invoke +"Hello World\n" +``` + +> [!IMPORTANT] +> The local server is only available in `DEBUG` mode. It will not start with `swift -c release run`. + +## Build & Package + +To build & archive the package, type the following commands. + +```bash +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/MyLambda/MyLambda.zip` + +## Deploy + +Here is how to deploy using the `aws` command line. + +```bash +aws lambda create-function \ +--function-name MyLambda \ +--zip-file fileb://.build/plugins/AWSLambdaPackager/outputs/AWSLambdaPackager/MyLambda/MyLambda.zip \ +--runtime provided.al2 \ +--handler provided \ +--architectures arm64 \ +--role arn:aws:iam:::role/lambda_basic_execution +``` + +The `--architectures` flag is only required when you build the binary on an Apple Silicon machine (Apple M1 or more recent). It defaults to `x64`. + +Be sure to replace with your actual AWS account ID (for example: 012345678901). + +## Invoke your Lambda function + +To invoke the Lambda function, use this `aws` command line. + +```bash +aws lambda invoke \ +--function-name MyLambda \ +--payload $(echo \"hello\" | base64) \ +out.txt && cat out.txt && rm out.txt +``` + +This should output the following result. + +``` +{ + "StatusCode": 200, + "ExecutedVersion": "$LATEST" +} +"Hello World\n" +``` + +## Undeploy + +When done testing, you can delete the Lambda function with this command. + +```bash +aws lambda delete-function --function-name MyLambda +``` + +## ⚠️ Security and Reliability Notice + +These are example applications for demonstration purposes. When deploying such infrastructure in production environments, we strongly encourage you to follow these best practices for improved security and resiliency: + +- Enable access logging on API Gateway ([documentation](https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html)) +- Ensure that AWS Lambda function is configured for function-level concurrent execution limit ([concurrency documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-concurrency.html), [configuration guide](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html)) +- Check encryption settings for Lambda environment variables ([documentation](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars-encryption.html)) +- Ensure that AWS Lambda function is configured for a Dead Letter Queue (DLQ) ([documentation](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async-retain-records.html#invocation-dlq)) +- Ensure that AWS Lambda function is configured inside a VPC when it needs to access private resources ([documentation](https://docs.aws.amazon.com/lambda/latest/dg/configuration-vpc.html), [code example](https://github.com/awslabs/swift-aws-lambda-runtime/tree/main/Examples/ServiceLifecycle%2BPostgres)) From 3c6092e4c535ccbf9fc574c0e5dfc18a2eece24a Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Thu, 14 May 2026 11:54:08 +0200 Subject: [PATCH 2/3] Update deps to avoid CI errors --- Package.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.swift b/Package.swift index 4faa2dd0f..6bfe02b48 100644 --- a/Package.swift +++ b/Package.swift @@ -32,10 +32,10 @@ let package = Package( ), ], dependencies: [ - .package(url: "https://github.com/apple/swift-nio.git", from: "2.95.0"), - .package(url: "https://github.com/apple/swift-log.git", from: "1.10.1"), - .package(url: "https://github.com/apple/swift-collections.git", from: "1.3.0"), - .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.10.1"), + .package(url: "https://github.com/apple/swift-nio.git", from: "2.99.0"), + .package(url: "https://github.com/apple/swift-log.git", from: "1.12.0"), + .package(url: "https://github.com/apple/swift-collections.git", from: "1.5.0"), + .package(url: "https://github.com/swift-server/swift-service-lifecycle.git", from: "2.11.0"), ], targets: [ .target( From 7e327ae73db7b2a2bdac91e3706555fc23803e7e Mon Sep 17 00:00:00 2001 From: Sebastien Stormacq Date: Thu, 14 May 2026 12:15:34 +0200 Subject: [PATCH 3/3] fix README: correct LambdaRuntime type, swift run syntax, and architecture name --- Examples/ResourcesPackaging/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Examples/ResourcesPackaging/README.md b/Examples/ResourcesPackaging/README.md index 2911ba20c..88718241b 100644 --- a/Examples/ResourcesPackaging/README.md +++ b/Examples/ResourcesPackaging/README.md @@ -6,7 +6,7 @@ This example demonstrates how to include static resources (such as text files, c ## Code -The code creates a `LambdaRuntime` struct with a handler that reads a bundled text file and returns its content. +The code creates a `LambdaRuntime` with a handler that reads a bundled text file and returns its content. The handler is `(event: String, context: LambdaContext)`. The function takes two arguments: - the event argument is a `String`. It is the parameter passed when invoking the function. @@ -42,7 +42,7 @@ curl -d '"hello"' http://127.0.0.1:7000/invoke ``` > [!IMPORTANT] -> The local server is only available in `DEBUG` mode. It will not start with `swift -c release run`. +> The local server is only available in `DEBUG` mode. It will not start with `swift run -c release`. ## Build & Package @@ -69,7 +69,7 @@ aws lambda create-function \ --role arn:aws:iam:::role/lambda_basic_execution ``` -The `--architectures` flag is only required when you build the binary on an Apple Silicon machine (Apple M1 or more recent). It defaults to `x64`. +The `--architectures` flag is only required when you build the binary on an Apple Silicon machine (Apple M1 or more recent). It defaults to `x86_64`. Be sure to replace with your actual AWS account ID (for example: 012345678901).