@@ -44,7 +44,7 @@ public struct Client {
44
44
throw . network( error)
45
45
}
46
46
guard let httpResponse = resp as? HTTPURLResponse else {
47
- throw . unexpectedResponse( data)
47
+ throw . unexpectedResponse( String ( data: data , encoding : . utf8 ) ?? " <non-utf8 data> " )
48
48
}
49
49
return HTTPResponse ( resp: httpResponse, data: data, req: req)
50
50
}
@@ -72,7 +72,7 @@ public struct Client {
72
72
73
73
func responseAsError( _ resp: HTTPResponse ) -> ClientError {
74
74
do {
75
- let body = try Client . decoder . decode ( Response . self, from: resp. data)
75
+ let body = try decode ( Response . self, from: resp. data)
76
76
let out = APIError (
77
77
response: body,
78
78
statusCode: resp. resp. statusCode,
@@ -81,7 +81,24 @@ public struct Client {
81
81
)
82
82
return . api( out)
83
83
} catch {
84
- return . unexpectedResponse( resp. data. prefix ( 1024 ) )
84
+ return . unexpectedResponse( String ( data: resp. data, encoding: . utf8) ?? " <non-utf8 data> " )
85
+ }
86
+ }
87
+
88
+ // Wrapper around JSONDecoder.decode that displays useful error messages from `DecodingError`.
89
+ func decode< T> ( _: T . Type , from data: Data ) throws ( ClientError) -> T where T: Decodable {
90
+ do {
91
+ return try Client . decoder. decode ( T . self, from: data)
92
+ } catch let DecodingError . keyNotFound( _, context) {
93
+ throw . unexpectedResponse( " Key not found: \( context. debugDescription) " )
94
+ } catch let DecodingError . valueNotFound( _, context) {
95
+ throw . unexpectedResponse( " Value not found: \( context. debugDescription) " )
96
+ } catch let DecodingError . typeMismatch( _, context) {
97
+ throw . unexpectedResponse( " Type mismatch: \( context. debugDescription) " )
98
+ } catch let DecodingError . dataCorrupted( context) {
99
+ throw . unexpectedResponse( " Data corrupted: \( context. debugDescription) " )
100
+ } catch {
101
+ throw . unexpectedResponse( String ( data: data. prefix ( 1024 ) , encoding: . utf8) ?? " <non-utf8 data> " )
85
102
}
86
103
}
87
104
}
@@ -119,7 +136,7 @@ public struct FieldValidation: Decodable, Sendable {
119
136
public enum ClientError : Error {
120
137
case api( APIError )
121
138
case network( any Error )
122
- case unexpectedResponse( Data )
139
+ case unexpectedResponse( String )
123
140
case encodeFailure( any Error )
124
141
125
142
public var description : String {
@@ -129,7 +146,7 @@ public enum ClientError: Error {
129
146
case let . network( error) :
130
147
error. localizedDescription
131
148
case let . unexpectedResponse( data) :
132
- " Unexpected or non HTTP response: \( data) "
149
+ " Unexpected response: \( data) "
133
150
case let . encodeFailure( error) :
134
151
" Failed to encode body: \( error. localizedDescription) "
135
152
}
0 commit comments