44// snippet-start:[lambda.swift.function.imports]
55import Foundation
66import AWSLambdaRuntime
7- import AWSS3
7+ @ preconcurrency import AWSS3
88
99import protocol AWSClientRuntime. AWSServiceError
1010import enum Smithy. ByteStream
1111// snippet-end:[lambda.swift.function.imports]
12+
1213// snippet-start:[lambda.swift.function.types]
1314// snippet-start:[lambda.swift.function.struct.request]
1415/// Represents the contents of the requests being received from the client.
@@ -19,6 +20,7 @@ struct Request: Decodable, Sendable {
1920 let body : String
2021}
2122// snippet-end:[lambda.swift.function.struct.request]
23+
2224// snippet-start:[lambda.swift.function.struct.response]
2325/// The contents of the response sent back to the client. This must be
2426/// `Encodable`.
@@ -29,131 +31,92 @@ struct Response: Encodable, Sendable {
2931 let body : String
3032}
3133// snippet-end:[lambda.swift.function.struct.response]
34+
3235// snippet-start:[lambda.swift.function.errors]
3336/// The errors that the Lambda function can return.
3437enum S3ExampleLambdaErrors : Error {
3538 /// A required environment variable is missing. The missing variable is
3639 /// specified.
3740 case noEnvironmentVariable( String )
38- /// The Amazon Simple Storage Service (S3) client couldn't be created.
39- case noS3Client
4041}
4142// snippet-end:[lambda.swift.function.errors]
4243// snippet-end:[lambda.swift.function.types]
4344
44- // snippet-start:[lambda.swift.function.handler]
45- /// A Swift AWS Lambda Runtime `LambdaHandler` lets you both perform needed
46- /// initialization and handle AWS Lambda requests. There are other handler
47- /// protocols available for other use cases.
48- @main
49- struct S3ExampleLambda : LambdaHandler {
50- let s3Client : S3Client ?
51-
52- // snippet-start:[lambda.swift.function.handler.init]
53- /// Initialize the AWS Lambda runtime.
54- ///
55- /// ^ The logger is a standard Swift logger. You can control the verbosity
56- /// by setting the `LOG_LEVEL` environment variable.
57- init ( context: LambdaInitializationContext ) async throws {
58- // Display the `LOG_LEVEL` configuration for this process.
59- context. logger. info (
60- " Log Level env var : \( ProcessInfo . processInfo. environment [ " LOG_LEVEL " ] ?? " info " ) "
61- )
45+ let currentRegion = ProcessInfo . processInfo. environment [ " AWS_REGION " ] ?? " us-east-1 "
46+ let s3Client = try S3Client ( region: currentRegion)
6247
63- // Initialize the Amazon S3 client. This single client is used for every
64- // request.
65- let currentRegion = ProcessInfo . processInfo. environment [ " AWS_REGION " ] ?? " us-east-1 "
66- self . s3Client = try ? S3Client ( region: currentRegion)
67- }
68- // snippet-end:[lambda.swift.function.handler.init]
69-
70- // snippet-start:[lambda.swift.function.handler.putobject]
71- /// Write the specified text into a given Amazon S3 bucket. The object's
72- /// name is based on the current time.
73- ///
74- /// - Parameters:
75- /// - s3Client: The `S3Client` to use when sending the object to the
76- /// bucket.
77- /// - bucketName: The name of the Amazon S3 bucket to put the object
78- /// into.
79- /// - body: The string to write into the new object.
80- ///
81- /// - Returns: A string indicating the name of the file created in the AWS
82- /// S3 bucket.
83- private func putObject( client: S3Client ,
84- bucketName: String ,
85- body: String ) async throws -> String {
86- // Generate an almost certainly unique object name based on the current
87- // timestamp.
88- let objectName = " \( Int ( Date ( ) . timeIntervalSince1970*1_000_000) ) .txt "
89-
90- // Create a Smithy `ByteStream` that represents the string to write into
91- // the bucket.
92- let inputStream = Smithy . ByteStream. data ( body. data ( using: . utf8) )
93-
94- // Store the text into an object in the Amazon S3 bucket.
95- let putObjectRequest = PutObjectInput (
48+ // snippet-start:[lambda.swift.function.putobject]
49+ /// Create a new object on Amazon S3 whose name is based on the current
50+ /// timestamp, containing the text specified.
51+ ///
52+ /// - Parameters:
53+ /// - body: The text to store in the new S3 object.
54+ /// - bucketName: The name of the Amazon S3 bucket to put the new object
55+ /// into.
56+ ///
57+ /// - Throws: Errors from `PutObject`.
58+ ///
59+ /// - Returns: The name of the new Amazon S3 object that contains the
60+ /// specified body text.
61+ func putObject( body: String , bucketName: String ) async throws -> String {
62+ // Generate an almost certainly unique object name based on the current
63+ // timestamp.
64+
65+ let objectName = " \( Int ( Date ( ) . timeIntervalSince1970*1_000_000) ) .txt "
66+
67+ // Create a Smithy `ByteStream` that represents the string to write into
68+ // the bucket.
69+
70+ let inputStream = Smithy . ByteStream. data ( body. data ( using: . utf8) )
71+
72+ // Store the text into an object in the Amazon S3 bucket.
73+
74+ _ = try await s3Client. putObject (
75+ input: PutObjectInput (
9676 body: inputStream,
9777 bucket: bucketName,
9878 key: objectName
9979 )
100- let _ = try await client. putObject ( input: putObjectRequest)
80+ )
81+
82+ // Return the name of the file
10183
102- // Return the name of the file.
103- return objectName
84+ return objectName
85+ }
86+ // snippet-end:[lambda.swift.function.putobject]
87+
88+ // snippet-start:[lambda.swift.function.runtime]
89+ let runtime = LambdaRuntime {
90+ ( event: Request , context: LambdaContext ) async throws -> Response in
91+
92+ var responseMessage : String
93+
94+ // Get the name of the bucket to write the new object into from the
95+ // environment variable `BUCKET_NAME`.
96+ guard let bucketName = ProcessInfo . processInfo. environment [ " BUCKET_NAME " ] else {
97+ context. logger. error ( " Set the environment variable BUCKET_NAME to the name of the S3 bucket to write files to. " )
98+ throw S3ExampleLambdaErrors . noEnvironmentVariable ( " BUCKET_NAME " )
10499 }
105- // snippet-end:[lambda.swift.function.handler.putobject]
106-
107- // snippet-start:[lambda.swift.function.handler.handle]
108- /// The Lambda function's entry point. Called by the Lambda runtime.
109- ///
110- /// - Parameters:
111- /// - event: The `Request` describing the request made by the
112- /// client.
113- /// - context: A `LambdaContext` describing the context in
114- /// which the lambda function is running.
115- ///
116- /// - Returns: A `Response` object that will be encoded to JSON and sent
117- /// to the client by the Lambda runtime.
118- func handle( _ event: Request , context: LambdaContext ) async throws -> Response {
119- // Get the bucket name from the environment.
120- guard let bucketName = ProcessInfo . processInfo. environment [ " BUCKET_NAME " ] else {
121- throw S3ExampleLambdaErrors . noEnvironmentVariable ( " BUCKET_NAME " )
122- }
123-
124- // Make sure the `S3Client` is valid.
125- guard let s3Client else {
126- throw S3ExampleLambdaErrors . noS3Client
127- }
128-
129- // Call the `putObject` function to store the object on Amazon S3.
130- var responseMessage : String
131- do {
132- let filename = try await putObject (
133- client: s3Client,
134- bucketName: bucketName,
135- body: event. body)
136-
137- // Generate the response text.
138- responseMessage = " The Lambda function has successfully stored your data in S3 with name \( filename) ' "
139-
140- // Send the success notification to the logger.
141- context. logger. info ( " Data successfully stored in S3. " )
142- } catch let error as AWSServiceError {
143- // Generate the error message.
144- responseMessage = " The Lambda function encountered an error and your data was not saved. Root cause: \( error. errorCode ?? " " ) - \( error. message ?? " " ) "
145-
146- // Send the error message to the logger.
147- context. logger. error ( " Failed to upload data to Amazon S3. " )
148- }
149-
150- // Return the response message. The AWS Lambda runtime will send it to the
151- // client.
152- return Response (
153- req_id: context. requestID,
154- body: responseMessage)
100+
101+ do {
102+ let filename = try await putObject ( body: event. body, bucketName: bucketName)
103+
104+ // Generate the response text and update the log.
105+ responseMessage = " The Lambda function has successfully stored your data in S3 with name ' \( filename) ' "
106+ context. logger. info ( " Data successfully stored in S3. " )
107+ } catch let error as AWSServiceError {
108+ // Generate the error message and update the log.
109+ responseMessage = " The Lambda function encountered an error and your data was not saved. Root cause: \( error. errorCode ?? " " ) - \( error. message ?? " " ) "
110+ context. logger. error ( " Failed to upload data to Amazon S3. " )
155111 }
156- // snippet-end:[lambda.swift.function.handler.handle]
112+
113+ return Response ( req_id: context. requestID, body: responseMessage)
157114}
158- // snippet-end:[lambda.swift.function.handler]
159- // snippet-end:[lambda.swift.function.complete]
115+ // snippet-end:[lambda.swift.function.runtime]
116+
117+ // Start up the runtime.
118+
119+ // snippet-start:[lambda.swift.function.start]
120+ try await runtime. run ( )
121+ // snippet-end:[lambda.swift.function.start]
122+ // snippet-end:[lambda.swift.function.complete]
0 commit comments