Skip to content

Commit 0025b1a

Browse files
authored
Add an encodable version of the APIGatewayResponse (#86)
Add a convenience initializer to the APIGatewayResponse v2 that accepts an Encodable object ### Motivation: Most Lambda developers will return a JSON object when exposing their function through the API Gateway. The current initializer only accepts a `String` body as per the AWS message definition. This obliges all developers to write two lines of code + error handling to encode their object and transform the `Data` to a string. ### Modifications: Add a new initializer that accepts a `body` as `Encodable` ```swift public init<Input: Encodable> ( statusCode: HTTPResponse.Status, headers: HTTPHeaders? = nil, body: Input, isBase64Encoded: Bool? = nil, cookies: [String]? = nil ) throws { ... } ``` ### Result: Developers can now pass a Swift struct to the APIGatewayResponse. ```swift let businessResponse = BusinessResponse(message: "Hello World", code: 200) return APIGatewayV2Response(statusCode: .ok, body: businessResponse) ```
1 parent 20fa5fe commit 0025b1a

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2022 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import HTTPTypes
16+
17+
#if canImport(FoundationEssentials)
18+
import class FoundationEssentials.JSONEncoder
19+
import struct FoundationEssentials.Data
20+
#else
21+
import class Foundation.JSONEncoder
22+
import struct Foundation.Data
23+
#endif
24+
25+
extension Encodable {
26+
fileprivate func string() throws -> String {
27+
let encoded = try JSONEncoder().encode(self)
28+
return String(decoding: encoded, as: UTF8.self)
29+
}
30+
}
31+
32+
extension APIGatewayResponse {
33+
34+
public init<Input: Encodable>(
35+
statusCode: HTTPResponse.Status,
36+
headers: HTTPHeaders? = nil,
37+
multiValueHeaders: HTTPMultiValueHeaders? = nil,
38+
encodableBody: Input
39+
) throws {
40+
self.init(
41+
statusCode: statusCode,
42+
headers: headers,
43+
multiValueHeaders: multiValueHeaders,
44+
body: try encodableBody.string(),
45+
isBase64Encoded: nil
46+
)
47+
}
48+
}
49+
50+
extension APIGatewayV2Response {
51+
52+
public init<Input: Encodable>(
53+
statusCode: HTTPResponse.Status,
54+
headers: HTTPHeaders? = nil,
55+
encodableBody: Input,
56+
cookies: [String]? = nil
57+
) throws {
58+
self.init(
59+
statusCode: statusCode,
60+
headers: headers,
61+
body: try encodableBody.string(),
62+
isBase64Encoded: nil,
63+
cookies: cookies
64+
)
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2020 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Foundation
16+
import Testing
17+
18+
@testable import AWSLambdaEvents
19+
20+
struct APIGatewayEncodableResponseTests {
21+
22+
// MARK: Encoding
23+
struct BusinessResponse: Codable, Equatable {
24+
let message: String
25+
let code: Int
26+
}
27+
28+
@Test
29+
func testResponseEncodingV2() throws {
30+
31+
// given
32+
let businessResponse = BusinessResponse(message: "Hello World", code: 200)
33+
34+
var response: APIGatewayV2Response? = nil
35+
#expect(throws: Never.self) {
36+
try response = APIGatewayV2Response(statusCode: .ok, encodableBody: businessResponse)
37+
}
38+
try #require(response?.body != nil)
39+
40+
// when
41+
let body = response?.body?.data(using: .utf8)
42+
try #require(body != nil)
43+
44+
#expect(throws: Never.self) {
45+
let encodedBody = try JSONDecoder().decode(BusinessResponse.self, from: body!)
46+
47+
// then
48+
#expect(encodedBody == businessResponse)
49+
}
50+
}
51+
52+
@Test
53+
func testResponseEncoding() throws {
54+
55+
// given
56+
let businessResponse = BusinessResponse(message: "Hello World", code: 200)
57+
58+
var response: APIGatewayResponse? = nil
59+
#expect(throws: Never.self) {
60+
try response = APIGatewayResponse(statusCode: .ok, encodableBody: businessResponse)
61+
}
62+
try #require(response?.body != nil)
63+
64+
// when
65+
let body = response?.body?.data(using: .utf8)
66+
try #require(body != nil)
67+
68+
#expect(throws: Never.self) {
69+
let encodedBody = try JSONDecoder().decode(BusinessResponse.self, from: body!)
70+
71+
// then
72+
#expect(encodedBody == businessResponse)
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)