Lambda SPM Resources
Posted Tuesday, February 6, 2024.
There is an additional step you need to do when packaging an SPM based Lambda that has resources.
Project Setup
File Structure
.
├── Sources
│ ├── Lambda
│ │ └── Handler.swift
│ └── Resources
│ └── info.txt
├── Package.swift
└── Package.resolved
Package.swift
// swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "Lambda",
platforms: [
.macOS(.v13)
],
dependencies: [
.package(url: "https://github.com/swift-server/swift-aws-lambda-runtime.git", from: "1.0.0-alpha.2")
],
targets: [
.executableTarget(
name: "Lambda",
dependencies: [
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime")
],
resources: [
.process("Resources")
]
)
]
)
Handler Definition
Imagine we had a handler that would look for a resource decided by the request parameters:
import AWSLambdaRuntime
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
struct Request: Codable {
let resource: String
let extension: String
}
struct Response: Codable {
let output: String
}
@main
struct Handler: SimpleLambdaHandler {
func handle(_ request: Request, context: LambdaContext) async throws -> Response {
guard let url = Bundle.module.url(forResource: request.resource, withExtension: request.extension) else {
throw Error.missingResource
}
let data = try Data(contentsOf: url)
let string = String(decoding: data, as: UTF8.self)
return .init(output: string)
}
enum Error: Swift.Error {
case missingResource
}
}
Without doing any extra steps, Bundle.module.url(forResource:withExtension:)
would return nil when running on the Lambda because the resources are not bundled properly (even if the resource was "supposed" to exist).
Steps to Mitigate
# use package plugin to bundle lambda
swift package --disable-sandbox archive --output-path .
# remove generated lambda zip
rm ./Lambda/Lambda.zip
# Copy Resources from build directory (PackageName_TargetName.resources)
cp -r .build/release/Lambda_Lambda.resources ./Lambda/Lambda_Lambda.resources
# zip new lambda with resources included
zip -r Lambda.zip Lambda_Lambda.resources bootstrap Lambda
Upload
Upload new Lambda zip to AWS
Tagged With: