Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Commit 6b11518

Browse files
Merge pull request #4 from Andrea-Scuderi/feature/async-http-client-1_0_0
Update Async-Http-Client to version 1.0.0
2 parents 47b8b9e + 8ca41c8 commit 6b11518

File tree

11 files changed

+1175
-27
lines changed

11 files changed

+1175
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
/Packages
44
/*.xcodeproj
55
default.profraw
6+
.swiftpm

Package.resolved

Lines changed: 13 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ let package = Package(
1515
dependencies: [
1616
// Dependencies declare other packages that this package depends on.
1717
//.package(path: "../aws-lambda-swift-sprinter-core/"),
18-
.package(url: "https://github.com/swift-sprinter/aws-lambda-swift-sprinter-core", from: "1.0.0-alpha.2"),
19-
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.0.0-alpha.4"),
18+
.package(url: "https://github.com/swift-sprinter/aws-lambda-swift-sprinter-core", from: "1.0.0-alpha.3"),
19+
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.0.0"),
20+
.package(url: "https://github.com/apple/swift-nio.git", from: "2.8.0"),
2021
],
2122
targets: [
2223
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
2324
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
2425
.target(
2526
name: "LambdaSwiftSprinterNioPlugin",
26-
dependencies: ["LambdaSwiftSprinter", "AsyncHTTPClient"]
27+
dependencies: ["LambdaSwiftSprinter", "AsyncHTTPClient", "NIOFoundationCompat"]
2728
),
2829
.testTarget(
2930
name: "LambdaSwiftSprinterNioPluginTests",

Sources/LambdaSwiftSprinterNioPlugin/LambdaApiNIO.swift

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,96 @@ import Foundation
2020
import LambdaSwiftSprinter
2121
import NIO
2222
import NIOHTTP1
23+
import NIOFoundationCompat
2324

25+
/**
26+
`SprinterNIO` implements the AWS Lambda Custom Runtime with `SwiftNIO`
27+
*/
2428
public typealias SprinterNIO = Sprinter<LambdaApiNIO>
2529

30+
31+
/**
32+
SprinterNIOError
33+
An error related to the `SprinterNIO`
34+
35+
### Errors: ###
36+
```
37+
case invalidResponse(HTTPResponseStatus)
38+
case invalidBuffer
39+
```
40+
*/
2641
public enum SprinterNIOError: Error {
42+
43+
/// Invalid Reponse with `HTTPResponseStatus`
2744
case invalidResponse(HTTPResponseStatus)
45+
46+
/// Invalid Buffer
2847
case invalidBuffer
2948
}
3049

50+
/** The amount of time the lambda waits for the next event.
51+
52+
The `default` timeout for a Lambda is `3600` seconds.
53+
*/
3154
public var lambdaRuntimeTimeout: TimeAmount = .seconds(3600)
55+
56+
/// The timeout used to create the instance of the `httpClient`
3257
public var timeout = HTTPClient.Configuration.Timeout(connect: lambdaRuntimeTimeout,
3358
read: lambdaRuntimeTimeout)
3459

35-
public var httpClient: HTTPClientProtocol = {
36-
let configuration = HTTPClient.Configuration(timeout: timeout)
37-
return HTTPClient(eventLoopGroupProvider: .createNew, configuration: configuration)
38-
}()
39-
60+
/** The HTTPClientProtocol defines a generic httpClient
61+
62+
Required for Unit Testing
63+
*/
4064
public protocol HTTPClientProtocol: class {
65+
var eventLoopGroup: EventLoopGroup { get }
4166
func get(url: String, deadline: NIODeadline?) -> EventLoopFuture<HTTPClient.Response>
4267
func post(url: String, body: HTTPClient.Body?, deadline: NIODeadline?) -> EventLoopFuture<HTTPClient.Response>
4368
func execute(request: HTTPClient.Request, deadline: NIODeadline?) -> EventLoopFuture<HTTPClient.Response>
4469
func syncShutdown() throws
4570
}
4671

72+
73+
/** The httpClient implementing `HTTPClientProtocol`
74+
75+
The `default` implementation is an `HTTPClient` defined in `AsyncHTTPClient`
76+
*/
77+
public var httpClient: HTTPClientProtocol = {
78+
let configuration = HTTPClient.Configuration(timeout: timeout)
79+
return HTTPClient(eventLoopGroupProvider: .createNew, configuration: configuration)
80+
}()
81+
4782
extension HTTPClient: HTTPClientProtocol {
4883

4984
}
5085

86+
/// The `LambdaApiNIO` class implements the LambdaAPI protocol using NIO.
87+
///
5188
public class LambdaApiNIO: LambdaAPI {
89+
5290
let urlBuilder: LambdaRuntimeAPIUrlBuilder
91+
92+
private let _nextInvocationRequest: HTTPClient.Request
5393

94+
/// Construct a `LambdaApiNIO` class.
95+
///
96+
/// - parameters
97+
/// - awsLambdaRuntimeAPI: AWS_LAMBDA_RUNTIME_API
5498
public required init(awsLambdaRuntimeAPI: String) throws {
5599
self.urlBuilder = try LambdaRuntimeAPIUrlBuilder(awsLambdaRuntimeAPI: awsLambdaRuntimeAPI)
100+
self._nextInvocationRequest = try HTTPClient.Request(url: urlBuilder.nextInvocationURL(), method: .GET)
56101
}
57102

103+
/// Call the next invocation API to get the next event. The response body contains the event data. Response headers contain the `RequestID` and other information.
104+
///
105+
/// - returns:
106+
/// - `(event: Data, responseHeaders: [AnyHashable: Any])` the event to process and the responseHeaders
107+
/// - throws:
108+
/// - `invalidBuffer` if the body is empty or the buffer doesn't contain data.
109+
/// - `invalidResponse(HTTPResponseStatus)` if the HTTP response is not valid.
58110
public func getNextInvocation() throws -> (event: Data, responseHeaders: [AnyHashable: Any]) {
59-
let request = try HTTPClient.Request(url: urlBuilder.nextInvocationURL(), method: .GET)
60111
let result = try httpClient.execute(
61-
request: request,
112+
request: _nextInvocationRequest,
62113
deadline: nil
63114
).wait()
64115

@@ -69,14 +120,22 @@ public class LambdaApiNIO: LambdaAPI {
69120
}
70121

71122
if let body = result.body,
72-
let buffer = body.getBytes(at: 0, length: body.readableBytes) {
73-
let data = buffer.data
123+
let data = body.getData(at: 0,
124+
length: body.readableBytes,
125+
byteTransferStrategy: .noCopy) {
74126
return (event: data, responseHeaders: httpHeaders.dictionary)
75127
} else {
76128
throw SprinterNIOError.invalidBuffer
77129
}
78130
}
79131

132+
/// Sends an invocation response to Lambda.
133+
///
134+
/// - parameters:
135+
/// - requestId: Request ID
136+
/// - httpBody: data body.
137+
/// - throws:
138+
/// - HttpClient errors
80139
public func postInvocationResponse(for requestId: String, httpBody: Data) throws {
81140
var request = try HTTPClient.Request(
82141
url: urlBuilder.invocationResponseURL(requestId: requestId),
@@ -89,6 +148,13 @@ public class LambdaApiNIO: LambdaAPI {
89148
).wait()
90149
}
91150

151+
/// Sends an invocation error to Lambda.
152+
///
153+
/// - parameters:
154+
/// - requestId: Request ID
155+
/// - error: error
156+
/// - throws:
157+
/// - HttpClient errors
92158
public func postInvocationError(for requestId: String, error: Error) throws {
93159
let errorMessage = String(describing: error)
94160
let invocationError = InvocationError(errorMessage: errorMessage,
@@ -105,6 +171,12 @@ public class LambdaApiNIO: LambdaAPI {
105171
).wait()
106172
}
107173

174+
/// Sends an initialization error to Lambda.
175+
///
176+
/// - parameters:
177+
/// - error: error
178+
/// - throws:
179+
/// - HttpClient errors
108180
public func postInitializationError(error: Error) throws {
109181
let errorMessage = String(describing: error)
110182
let invocationError = InvocationError(errorMessage: errorMessage,

0 commit comments

Comments
 (0)