Skip to content

Commit 58d548f

Browse files
committed
improve error handling to match node sdk
1 parent 51e9f8a commit 58d548f

File tree

6 files changed

+65
-22
lines changed

6 files changed

+65
-22
lines changed

Package.resolved

+20-20
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,26 @@
66
"kind" : "remoteSourceControl",
77
"location" : "https://github.com/swift-server/async-http-client.git",
88
"state" : {
9-
"revision" : "0ae99db85b2b9d1e79b362bd31fd1ffe492f7c47",
10-
"version" : "1.21.2"
9+
"revision" : "0a9b72369b9d87ab155ef585ef50700a34abf070",
10+
"version" : "1.23.1"
1111
}
1212
},
1313
{
1414
"identity" : "cwlcatchexception",
1515
"kind" : "remoteSourceControl",
1616
"location" : "https://github.com/mattgallagher/CwlCatchException.git",
1717
"state" : {
18-
"revision" : "3ef6999c73b6938cc0da422f2c912d0158abb0a0",
19-
"version" : "2.2.0"
18+
"revision" : "07b2ba21d361c223e25e3c1e924288742923f08c",
19+
"version" : "2.2.1"
2020
}
2121
},
2222
{
2323
"identity" : "cwlpreconditiontesting",
2424
"kind" : "remoteSourceControl",
2525
"location" : "https://github.com/mattgallagher/CwlPreconditionTesting.git",
2626
"state" : {
27-
"revision" : "2ef56b2caf25f55fa7eef8784c30d5a767550f54",
28-
"version" : "2.2.1"
27+
"revision" : "0139c665ebb45e6a9fbdb68aabfd7c39f3fe0071",
28+
"version" : "2.2.2"
2929
}
3030
},
3131
{
@@ -60,8 +60,8 @@
6060
"kind" : "remoteSourceControl",
6161
"location" : "https://github.com/apple/swift-collections.git",
6262
"state" : {
63-
"revision" : "3d2dc41a01f9e49d84f0a3925fb858bed64f702d",
64-
"version" : "1.1.2"
63+
"revision" : "671108c96644956dddcd89dd59c203dcdb36cec7",
64+
"version" : "1.1.4"
6565
}
6666
},
6767
{
@@ -87,44 +87,44 @@
8787
"kind" : "remoteSourceControl",
8888
"location" : "https://github.com/apple/swift-nio.git",
8989
"state" : {
90-
"revision" : "4c4453b489cf76e6b3b0f300aba663eb78182fad",
91-
"version" : "2.70.0"
90+
"revision" : "914081701062b11e3bb9e21accc379822621995e",
91+
"version" : "2.76.1"
9292
}
9393
},
9494
{
9595
"identity" : "swift-nio-extras",
9696
"kind" : "remoteSourceControl",
9797
"location" : "https://github.com/apple/swift-nio-extras.git",
9898
"state" : {
99-
"revision" : "d1ead62745cc3269e482f1c51f27608057174379",
100-
"version" : "1.24.0"
99+
"revision" : "2e9746cfc57554f70b650b021b6ae4738abef3e6",
100+
"version" : "1.24.1"
101101
}
102102
},
103103
{
104104
"identity" : "swift-nio-http2",
105105
"kind" : "remoteSourceControl",
106106
"location" : "https://github.com/apple/swift-nio-http2.git",
107107
"state" : {
108-
"revision" : "b5f7062b60e4add1e8c343ba4eb8da2e324b3a94",
109-
"version" : "1.34.0"
108+
"revision" : "eaa71bb6ae082eee5a07407b1ad0cbd8f48f9dca",
109+
"version" : "1.34.1"
110110
}
111111
},
112112
{
113113
"identity" : "swift-nio-ssl",
114114
"kind" : "remoteSourceControl",
115115
"location" : "https://github.com/apple/swift-nio-ssl.git",
116116
"state" : {
117-
"revision" : "a9fa5efd86e7ce2e5c1b6de113262e58035ca251",
118-
"version" : "2.27.1"
117+
"revision" : "d7ceaf0e4d8001cd35cdc12e42cdd281e9e564e8",
118+
"version" : "2.28.0"
119119
}
120120
},
121121
{
122122
"identity" : "swift-nio-transport-services",
123123
"kind" : "remoteSourceControl",
124124
"location" : "https://github.com/apple/swift-nio-transport-services.git",
125125
"state" : {
126-
"revision" : "38ac8221dd20674682148d6451367f89c2652980",
127-
"version" : "1.21.0"
126+
"revision" : "bbd5e63cf949b7db0c9edaf7a21e141c52afe214",
127+
"version" : "1.23.0"
128128
}
129129
},
130130
{
@@ -141,8 +141,8 @@
141141
"kind" : "remoteSourceControl",
142142
"location" : "https://github.com/apple/swift-system.git",
143143
"state" : {
144-
"revision" : "d2ba781702a1d8285419c15ee62fd734a9437ff5",
145-
"version" : "1.3.2"
144+
"revision" : "c8a44d836fe7913603e246acab7c528c2e780168",
145+
"version" : "1.4.0"
146146
}
147147
}
148148
],

Sources/IndiePitcherSwift/IndiePitcherSwift.swift

+24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ import NIOCore
55
import NIOHTTP1
66
import NIOFoundationCompat
77

8+
extension HTTPClientResponse {
9+
var isOk: Bool {
10+
status.code >= 200 && status.code < 400
11+
}
12+
}
13+
814
/// IndiePitcher SDK.
915
/// This SDK is only intended for server-side Swift use. Do not embed the secret API key in client-side code for security reasons.
1016
public struct IndiePitcher: Sendable {
@@ -61,6 +67,12 @@ public struct IndiePitcher: Sendable {
6167

6268
let response = try await client.execute(request, timeout: requestTimeout)
6369
let responseData = try await response.body.collect(upTo: maxResponseSize)
70+
71+
guard response.isOk else {
72+
let error = try? jsonDecoder.decode(ErrorResponse.self, from: responseData)
73+
throw IndiePitcherRequestError(statusCode: response.status.code, reason: error?.reason ?? "Unknown reason")
74+
}
75+
6476
return try self.jsonDecoder.decode(T.self, from: responseData)
6577
}
6678

@@ -76,6 +88,12 @@ public struct IndiePitcher: Sendable {
7688

7789
let response = try await client.execute(request, timeout: requestTimeout)
7890
let responseData = try await response.body.collect(upTo: maxResponseSize)
91+
92+
guard response.isOk else {
93+
let error = try? jsonDecoder.decode(ErrorResponse.self, from: responseData)
94+
throw IndiePitcherRequestError(statusCode: response.status.code, reason: error?.reason ?? "Unknown reason")
95+
}
96+
7997
return try self.jsonDecoder.decode(T.self, from: responseData)
8098
}
8199

@@ -89,6 +107,12 @@ public struct IndiePitcher: Sendable {
89107

90108
let response = try await client.execute(request, timeout: requestTimeout)
91109
let responseData = try await response.body.collect(upTo: maxResponseSize)
110+
111+
guard response.isOk else {
112+
let error = try? jsonDecoder.decode(ErrorResponse.self, from: responseData)
113+
throw IndiePitcherRequestError(statusCode: response.status.code, reason: error?.reason ?? "Unknown reason")
114+
}
115+
92116
return try self.jsonDecoder.decode(T.self, from: responseData)
93117
}
94118

Sources/IndiePitcherSwift/dtos.swift

-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,6 @@ public struct MailingList: Codable {
344344
public var numSubscribers: Int
345345
}
346346

347-
348347
/// A portal session that allows a contact to manage their email list subscriptions when redirected to returned `url`. A session is valid for 30 minutes.
349348
public struct MailingListPortalSession: Codable {
350349
public init(url: URL, expiresAt: Date, returnURL: URL) {
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public struct IndiePitcherRequestError: Error, Equatable {
2+
var statusCode: UInt
3+
var reason: String
4+
5+
public init(statusCode: UInt, reason: String) {
6+
self.statusCode = statusCode
7+
self.reason = reason
8+
}
9+
}

Sources/IndiePitcherSwift/responses.swift

+4
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,7 @@ public struct PagedDataResponse<T: Codable>: Codable {
6767
public var metadata: PageMetadata
6868
}
6969

70+
struct ErrorResponse: Codable {
71+
var reason: String
72+
var error: Bool
73+
}

Tests/IndiePitcherSwiftTests/IndiePitcherSwiftTests.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,14 @@ final class IndiePitcherSwiftTests: XCTestCase {
1212
}
1313

1414
override func tearDown() async throws {
15-
// no need to shut down shared client
15+
// work around API rate limiting
16+
try await Task.sleep(for: .seconds(1))
17+
}
18+
19+
func testThrowRequestError() async {
20+
let indiePitcherx = IndiePitcher(apiKey: "fake")
21+
await expect({try await indiePitcherx.listMailingLists()})
22+
.to(throwError(IndiePitcherRequestError(statusCode: 401, reason: "Unauthorized")))
1623
}
1724

1825
func testSendTransactionalEmailMarkdown() async throws {

0 commit comments

Comments
 (0)