Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions swift/example_code/lambda/using-lambda-runtime/Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version: 5.10
// swift-tools-version: 6.0
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -20,7 +20,7 @@ let package = Package(
dependencies: [
.package(
url: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
from: "1.0.0-alpha"),
from: "2.0.0-beta.1"),
.package(url: "https://github.com/awslabs/aws-sdk-swift.git",
from: "1.0.0"),
],
Expand Down
183 changes: 73 additions & 110 deletions swift/example_code/lambda/using-lambda-runtime/Sources/lambda.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
// snippet-start:[lambda.swift.function.imports]
import Foundation
import AWSLambdaRuntime
import AWSS3
@preconcurrency import AWSS3

import protocol AWSClientRuntime.AWSServiceError
import enum Smithy.ByteStream
// snippet-end:[lambda.swift.function.imports]

// snippet-start:[lambda.swift.function.types]
// snippet-start:[lambda.swift.function.struct.request]
/// Represents the contents of the requests being received from the client.
Expand All @@ -19,6 +20,7 @@ struct Request: Decodable, Sendable {
let body: String
}
// snippet-end:[lambda.swift.function.struct.request]

// snippet-start:[lambda.swift.function.struct.response]
/// The contents of the response sent back to the client. This must be
/// `Encodable`.
Expand All @@ -29,131 +31,92 @@ struct Response: Encodable, Sendable {
let body: String
}
// snippet-end:[lambda.swift.function.struct.response]

// snippet-start:[lambda.swift.function.errors]
/// The errors that the Lambda function can return.
enum S3ExampleLambdaErrors: Error {
/// A required environment variable is missing. The missing variable is
/// specified.
case noEnvironmentVariable(String)
/// The Amazon Simple Storage Service (S3) client couldn't be created.
case noS3Client
}
// snippet-end:[lambda.swift.function.errors]
// snippet-end:[lambda.swift.function.types]

// snippet-start:[lambda.swift.function.handler]
/// A Swift AWS Lambda Runtime `LambdaHandler` lets you both perform needed
/// initialization and handle AWS Lambda requests. There are other handler
/// protocols available for other use cases.
@main
struct S3ExampleLambda: LambdaHandler {
let s3Client: S3Client?

// snippet-start:[lambda.swift.function.handler.init]
/// Initialize the AWS Lambda runtime.
///
/// ^ The logger is a standard Swift logger. You can control the verbosity
/// by setting the `LOG_LEVEL` environment variable.
init(context: LambdaInitializationContext) async throws {
// Display the `LOG_LEVEL` configuration for this process.
context.logger.info(
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )"
)
let currentRegion = ProcessInfo.processInfo.environment["AWS_REGION"] ?? "us-east-1"
let s3Client = try S3Client(region: currentRegion)

// Initialize the Amazon S3 client. This single client is used for every
// request.
let currentRegion = ProcessInfo.processInfo.environment["AWS_REGION"] ?? "us-east-1"
self.s3Client = try? S3Client(region: currentRegion)
}
// snippet-end:[lambda.swift.function.handler.init]

// snippet-start:[lambda.swift.function.handler.putobject]
/// Write the specified text into a given Amazon S3 bucket. The object's
/// name is based on the current time.
///
/// - Parameters:
/// - s3Client: The `S3Client` to use when sending the object to the
/// bucket.
/// - bucketName: The name of the Amazon S3 bucket to put the object
/// into.
/// - body: The string to write into the new object.
///
/// - Returns: A string indicating the name of the file created in the AWS
/// S3 bucket.
private func putObject(client: S3Client,
bucketName: String,
body: String) async throws -> String {
// Generate an almost certainly unique object name based on the current
// timestamp.
let objectName = "\(Int(Date().timeIntervalSince1970*1_000_000)).txt"

// Create a Smithy `ByteStream` that represents the string to write into
// the bucket.
let inputStream = Smithy.ByteStream.data(body.data(using: .utf8))

// Store the text into an object in the Amazon S3 bucket.
let putObjectRequest = PutObjectInput(
// snippet-start:[lambda.swift.function.putobject]
/// Create a new object on Amazon S3 whose name is based on the current
/// timestamp, containing the text specified.
///
/// - Parameters:
/// - body: The text to store in the new S3 object.
/// - bucketName: The name of the Amazon S3 bucket to put the new object
/// into.
///
/// - Throws: Errors from `PutObject`.
///
/// - Returns: The name of the new Amazon S3 object that contains the
/// specified body text.
func putObject(body: String, bucketName: String) async throws -> String {
// Generate an almost certainly unique object name based on the current
// timestamp.

let objectName = "\(Int(Date().timeIntervalSince1970*1_000_000)).txt"

// Create a Smithy `ByteStream` that represents the string to write into
// the bucket.

let inputStream = Smithy.ByteStream.data(body.data(using: .utf8))

// Store the text into an object in the Amazon S3 bucket.

_ = try await s3Client.putObject(
input: PutObjectInput(
body: inputStream,
bucket: bucketName,
key: objectName
)
let _ = try await client.putObject(input: putObjectRequest)
)

// Return the name of the file

// Return the name of the file.
return objectName
return objectName
}
// snippet-end:[lambda.swift.function.putobject]

// snippet-start:[lambda.swift.function.runtime]
let runtime = LambdaRuntime {
(event: Request, context: LambdaContext) async throws -> Response in

var responseMessage: String

// Get the name of the bucket to write the new object into from the
// environment variable `BUCKET_NAME`.
guard let bucketName = ProcessInfo.processInfo.environment["BUCKET_NAME"] else {
context.logger.error("Set the environment variable BUCKET_NAME to the name of the S3 bucket to write files to.")
throw S3ExampleLambdaErrors.noEnvironmentVariable("BUCKET_NAME")
}
// snippet-end:[lambda.swift.function.handler.putobject]

// snippet-start:[lambda.swift.function.handler.handle]
/// The Lambda function's entry point. Called by the Lambda runtime.
///
/// - Parameters:
/// - event: The `Request` describing the request made by the
/// client.
/// - context: A `LambdaContext` describing the context in
/// which the lambda function is running.
///
/// - Returns: A `Response` object that will be encoded to JSON and sent
/// to the client by the Lambda runtime.
func handle(_ event: Request, context: LambdaContext) async throws -> Response {
// Get the bucket name from the environment.
guard let bucketName = ProcessInfo.processInfo.environment["BUCKET_NAME"] else {
throw S3ExampleLambdaErrors.noEnvironmentVariable("BUCKET_NAME")
}

// Make sure the `S3Client` is valid.
guard let s3Client else {
throw S3ExampleLambdaErrors.noS3Client
}

// Call the `putObject` function to store the object on Amazon S3.
var responseMessage: String
do {
let filename = try await putObject(
client: s3Client,
bucketName: bucketName,
body: event.body)

// Generate the response text.
responseMessage = "The Lambda function has successfully stored your data in S3 with name \(filename)'"

// Send the success notification to the logger.
context.logger.info("Data successfully stored in S3.")
} catch let error as AWSServiceError {
// Generate the error message.
responseMessage = "The Lambda function encountered an error and your data was not saved. Root cause: \(error.errorCode ?? "") - \(error.message ?? "")"

// Send the error message to the logger.
context.logger.error("Failed to upload data to Amazon S3.")
}

// Return the response message. The AWS Lambda runtime will send it to the
// client.
return Response(
req_id: context.requestID,
body: responseMessage)

do {
let filename = try await putObject(body: event.body, bucketName: bucketName)

// Generate the response text and update the log.
responseMessage = "The Lambda function has successfully stored your data in S3 with name '\(filename)'"
context.logger.info("Data successfully stored in S3.")
} catch let error as AWSServiceError {
// Generate the error message and update the log.
responseMessage = "The Lambda function encountered an error and your data was not saved. Root cause: \(error.errorCode ?? "") - \(error.message ?? "")"
context.logger.error("Failed to upload data to Amazon S3.")
}
// snippet-end:[lambda.swift.function.handler.handle]

return Response(req_id: context.requestID, body: responseMessage)
}
// snippet-end:[lambda.swift.function.handler]
// snippet-end:[lambda.swift.function.complete]
// snippet-end:[lambda.swift.function.runtime]

// Start up the runtime.

// snippet-start:[lambda.swift.function.start]
try await runtime.run()
// snippet-end:[lambda.swift.function.start]
// snippet-end:[lambda.swift.function.complete]
2 changes: 0 additions & 2 deletions swift/example_code/lambda/using-lambda-runtime/test.sh
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
#!/bin/bash
echo "No automated tests available."
Loading