Skip to content

Commit 4f1f09c

Browse files
Refactors erroring, exposes error codes
1 parent bb5cafa commit 4f1f09c

File tree

4 files changed

+86
-70
lines changed

4 files changed

+86
-70
lines changed

Sources/GraphQLTransportWS/Client.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ public class Client {
2626
) {
2727
self.messenger = messenger
2828
messenger.onRecieve { message in
29-
guard let messenger = self.messenger else { return }
30-
3129
self.onMessage(message, self)
3230

3331
// Detect and ignore error responses.
@@ -37,8 +35,7 @@ public class Client {
3735
}
3836

3937
guard let json = message.data(using: .utf8) else {
40-
let error = GraphqlTransportWsError.invalidEncoding()
41-
messenger.error(error.message, code: error.code)
38+
self.error(.invalidEncoding())
4239
return
4340
}
4441

@@ -47,43 +44,37 @@ public class Client {
4744
response = try self.decoder.decode(Response.self, from: json)
4845
}
4946
catch {
50-
let error = GraphqlTransportWsError.noType()
51-
messenger.error(error.message, code: error.code)
47+
self.error(.noType())
5248
return
5349
}
5450

5551
switch response.type {
5652
case .connectionAck:
5753
guard let connectionAckResponse = try? self.decoder.decode(ConnectionAckResponse.self, from: json) else {
58-
let error = GraphqlTransportWsError.invalidResponseFormat(messageType: .connectionAck)
59-
messenger.error(error.message, code: error.code)
54+
self.error(.invalidResponseFormat(messageType: .connectionAck))
6055
return
6156
}
6257
self.onConnectionAck(connectionAckResponse, self)
6358
case .next:
6459
guard let nextResponse = try? self.decoder.decode(NextResponse.self, from: json) else {
65-
let error = GraphqlTransportWsError.invalidResponseFormat(messageType: .next)
66-
messenger.error(error.message, code: error.code)
60+
self.error(.invalidResponseFormat(messageType: .next))
6761
return
6862
}
6963
self.onNext(nextResponse, self)
7064
case .error:
7165
guard let errorResponse = try? self.decoder.decode(ErrorResponse.self, from: json) else {
72-
let error = GraphqlTransportWsError.invalidResponseFormat(messageType: .error)
73-
messenger.error(error.message, code: error.code)
66+
self.error(.invalidResponseFormat(messageType: .error))
7467
return
7568
}
7669
self.onError(errorResponse, self)
7770
case .complete:
7871
guard let completeResponse = try? self.decoder.decode(CompleteResponse.self, from: json) else {
79-
let error = GraphqlTransportWsError.invalidResponseFormat(messageType: .complete)
80-
messenger.error(error.message, code: error.code)
72+
self.error(.invalidResponseFormat(messageType: .complete))
8173
return
8274
}
8375
self.onComplete(completeResponse, self)
8476
case .unknown:
85-
let error = GraphqlTransportWsError.invalidType()
86-
messenger.error(error.message, code: error.code)
77+
self.error(.invalidType())
8778
}
8879
}
8980
}
@@ -148,4 +139,10 @@ public class Client {
148139
).toJSON(encoder)
149140
)
150141
}
142+
143+
/// Send an error through the messenger and close the connection
144+
private func error(_ error: GraphQLTransportWSError) {
145+
guard let messenger = messenger else { return }
146+
messenger.error(error.message, code: error.code.rawValue)
147+
}
151148
}
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,115 @@
11
// Copyright (c) 2021 PassiveLogic, Inc.
22

3-
struct GraphqlTransportWsError: Error {
3+
struct GraphQLTransportWSError: Error {
44
let message: String
5-
let code: Int
5+
let code: ErrorCode
66

7-
init(_ message: String, code: Int) {
7+
init(_ message: String, code: ErrorCode) {
88
self.message = message
99
self.code = code
1010
}
1111

1212
static func unauthorized() -> Self {
1313
return self.init(
1414
"Unauthorized",
15-
code: 4401
15+
code: .unauthorized
1616
)
1717
}
1818

19-
static func tooManyInitializations() -> Self {
19+
static func notInitialized() -> Self {
2020
return self.init(
21-
"Too many initialisation requests",
22-
code: 4429
21+
"Connection not initialized",
22+
code: .notInitialized
2323
)
2424
}
2525

26-
static func notInitialized() -> Self {
26+
static func tooManyInitializations() -> Self {
2727
return self.init(
28-
"Connection not initialized",
29-
code: 4407
28+
"Too many initialisation requests",
29+
code: .tooManyInitializations
3030
)
3131
}
3232

3333
static func subscriberAlreadyExists(id: String) -> Self {
3434
return self.init(
3535
"Subscriber for \(id) already exists",
36-
code: 4409
36+
code: .subscriberAlreadyExists
3737
)
3838
}
3939

4040
static func invalidEncoding() -> Self {
4141
return self.init(
4242
"Message was not encoded in UTF8",
43-
code: 4400
43+
code: .invalidEncoding
4444
)
4545
}
4646

4747
static func noType() -> Self {
4848
return self.init(
4949
"Message has no 'type' field",
50-
code: 4400
50+
code: .noType
5151
)
5252
}
5353

5454
static func invalidType() -> Self {
5555
return self.init(
5656
"Message 'type' value does not match supported types",
57-
code: 4400
57+
code: .invalidType
5858
)
5959
}
6060

6161
static func invalidRequestFormat(messageType: RequestMessageType) -> Self {
6262
return self.init(
6363
"Request message doesn't match '\(messageType.rawValue)' JSON format",
64-
code: 4400
64+
code: .invalidRequestFormat
6565
)
6666
}
6767

6868
static func invalidResponseFormat(messageType: ResponseMessageType) -> Self {
6969
return self.init(
7070
"Response message doesn't match '\(messageType.rawValue)' JSON format",
71-
code: 4400
71+
code: .invalidResponseFormat
7272
)
7373
}
7474

7575
static func internalAPIStreamIssue() -> Self {
7676
return self.init(
7777
"API Response did not result in a stream type",
78-
code: 4400
78+
code: .internalAPIStreamIssue
7979
)
8080
}
8181

8282
static func graphQLError(_ error: Error) -> Self {
8383
return self.init(
8484
"\(error)",
85-
code: 4400
85+
code: .graphQLError
8686
)
8787
}
8888
}
89+
90+
/// Error codes for miscellaneous issues
91+
public enum ErrorCode: Int, CustomStringConvertible {
92+
// Miscellaneous
93+
case miscellaneous = 4400
94+
95+
// Internal errors
96+
case graphQLError = 4401
97+
case internalAPIStreamIssue = 4402
98+
99+
// Message errors
100+
case invalidEncoding = 4410
101+
case noType = 4411
102+
case invalidType = 4412
103+
case invalidRequestFormat = 4413
104+
case invalidResponseFormat = 4414
105+
106+
// Initialization errors
107+
case unauthorized = 4430
108+
case notInitialized = 4431
109+
case tooManyInitializations = 4432
110+
case subscriberAlreadyExists = 4433
111+
112+
public var description: String {
113+
return "\(self.rawValue)"
114+
}
115+
}

Sources/GraphQLTransportWS/Server.swift

Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ public class Server {
4242
self.onSubscribe = onSubscribe
4343

4444
messenger.onRecieve { message in
45-
guard let messenger = self.messenger else { return }
46-
4745
self.onMessage(message)
4846

4947
// Detect and ignore error responses.
@@ -53,8 +51,7 @@ public class Server {
5351
}
5452

5553
guard let data = message.data(using: .utf8) else {
56-
let error = GraphqlTransportWsError.invalidEncoding()
57-
messenger.error(error.message, code: error.code)
54+
self.error(.invalidEncoding())
5855
return
5956
}
6057

@@ -63,36 +60,31 @@ public class Server {
6360
request = try self.decoder.decode(Request.self, from: data)
6461
}
6562
catch {
66-
let error = GraphqlTransportWsError.noType()
67-
messenger.error(error.message, code: error.code)
63+
self.error(.noType())
6864
return
6965
}
7066

7167
switch request.type {
7268
case .connectionInit:
7369
guard let connectionInitRequest = try? self.decoder.decode(ConnectionInitRequest.self, from: data) else {
74-
let error = GraphqlTransportWsError.invalidRequestFormat(messageType: .connectionInit)
75-
messenger.error(error.message, code: error.code)
70+
self.error(.invalidRequestFormat(messageType: .connectionInit))
7671
return
7772
}
78-
self.onConnectionInit(connectionInitRequest, messenger)
73+
self.onConnectionInit(connectionInitRequest)
7974
case .subscribe:
8075
guard let subscribeRequest = try? self.decoder.decode(SubscribeRequest.self, from: data) else {
81-
let error = GraphqlTransportWsError.invalidRequestFormat(messageType: .subscribe)
82-
messenger.error(error.message, code: error.code)
76+
self.error(.invalidRequestFormat(messageType: .subscribe))
8377
return
8478
}
85-
self.onSubscribe(subscribeRequest, messenger)
79+
self.onSubscribe(subscribeRequest)
8680
case .complete:
8781
guard let completeRequest = try? self.decoder.decode(CompleteRequest.self, from: data) else {
88-
let error = GraphqlTransportWsError.invalidRequestFormat(messageType: .complete)
89-
messenger.error(error.message, code: error.code)
82+
self.error(.invalidRequestFormat(messageType: .complete))
9083
return
9184
}
92-
self.onComplete(completeRequest, messenger)
85+
self.onComplete(completeRequest)
9386
case .unknown:
94-
let error = GraphqlTransportWsError.invalidType()
95-
messenger.error(error.message, code: error.code)
87+
self.error(.invalidType())
9688
}
9789
}
9890
}
@@ -115,29 +107,26 @@ public class Server {
115107
self.onMessage = callback
116108
}
117109

118-
private func onConnectionInit(_ connectionInitRequest: ConnectionInitRequest, _ messenger: Messenger) {
110+
private func onConnectionInit(_ connectionInitRequest: ConnectionInitRequest) {
119111
guard !initialized else {
120-
let error = GraphqlTransportWsError.tooManyInitializations()
121-
messenger.error(error.message, code: error.code)
112+
self.error(.tooManyInitializations())
122113
return
123114
}
124115

125116
do {
126117
try self.auth(connectionInitRequest)
127118
}
128119
catch {
129-
let error = GraphqlTransportWsError.unauthorized()
130-
messenger.error(error.message, code: error.code)
120+
self.error(.unauthorized())
131121
return
132122
}
133123
initialized = true
134124
self.sendConnectionAck()
135125
}
136126

137-
private func onSubscribe(_ subscribeRequest: SubscribeRequest, _ messenger: Messenger) {
127+
private func onSubscribe(_ subscribeRequest: SubscribeRequest) {
138128
guard initialized else {
139-
let error = GraphqlTransportWsError.notInitialized()
140-
messenger.error(error.message, code: error.code)
129+
self.error(.notInitialized())
141130
return
142131
}
143132

@@ -156,11 +145,10 @@ public class Server {
156145
if isStreaming {
157146
let subscribeFuture = onSubscribe(graphQLRequest)
158147
subscribeFuture.whenSuccess { [weak self] result in
159-
guard let self = self, let messenger = self.messenger else { return }
148+
guard let self = self else { return }
160149
guard let streamOpt = result.stream else {
161150
// API issue - subscribe resolver isn't stream
162-
let error = GraphqlTransportWsError.internalAPIStreamIssue()
163-
messenger.error(error.message, code: error.code)
151+
self.error(.internalAPIStreamIssue())
164152
return
165153
}
166154
let stream = streamOpt as! ObservableSubscriptionEventStream
@@ -188,8 +176,7 @@ public class Server {
188176
).disposed(by: self.disposeBag)
189177
}
190178
subscribeFuture.whenFailure { error in
191-
let error = GraphqlTransportWsError.graphQLError(error)
192-
_ = messenger.error(error.message, code: error.code)
179+
self.error(.graphQLError(error))
193180
}
194181
}
195182
else {
@@ -207,10 +194,9 @@ public class Server {
207194
}
208195
}
209196

210-
private func onComplete(_: CompleteRequest, _ messenger: Messenger) {
197+
private func onComplete(_: CompleteRequest) {
211198
guard initialized else {
212-
let error = GraphqlTransportWsError.notInitialized()
213-
messenger.error(error.message, code: error.code)
199+
self.error(.notInitialized())
214200
return
215201
}
216202
onExit()
@@ -265,4 +251,10 @@ public class Server {
265251
private func sendError(_ errorMessage: String, id: String) {
266252
self.sendError(GraphQLError(message: errorMessage), id: id)
267253
}
254+
255+
/// Send an error through the messenger and close the connection
256+
private func error(_ error: GraphQLTransportWSError) {
257+
guard let messenger = messenger else { return }
258+
messenger.error(error.message, code: error.code.rawValue)
259+
}
268260
}

Tests/GraphQLTransportWSTests/GraphQLTransportWSTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import XCTest
88

99
@testable import GraphQLTransportWS
1010

11-
class GraphqlTransportWsTests: XCTestCase {
11+
class GraphqlTransportWSTests: XCTestCase {
1212
var clientMessenger: TestMessenger!
1313
var serverMessenger: TestMessenger!
1414
var server: Server!
@@ -68,7 +68,7 @@ class GraphqlTransportWsTests: XCTestCase {
6868
wait(for: [completeExpectation], timeout: 2)
6969
XCTAssertEqual(
7070
messages,
71-
["4407: Connection not initialized"]
71+
["\(ErrorCode.notInitialized): Connection not initialized"]
7272
)
7373
}
7474

@@ -96,7 +96,7 @@ class GraphqlTransportWsTests: XCTestCase {
9696
wait(for: [completeExpectation], timeout: 2)
9797
XCTAssertEqual(
9898
messages,
99-
["4401: Unauthorized"]
99+
["\(ErrorCode.unauthorized): Unauthorized"]
100100
)
101101
}
102102

0 commit comments

Comments
 (0)