@@ -44,7 +44,7 @@ public struct Client {
4444 throw . network( error)
4545 }
4646 guard let httpResponse = resp as? HTTPURLResponse else {
47- throw . unexpectedResponse( data)
47+ throw . unexpectedResponse( String ( data: data , encoding : . utf8 ) ?? " <non-utf8 data> " )
4848 }
4949 return HTTPResponse ( resp: httpResponse, data: data, req: req)
5050 }
@@ -72,7 +72,7 @@ public struct Client {
7272
7373 func responseAsError( _ resp: HTTPResponse ) -> ClientError {
7474 do {
75- let body = try Client . decoder . decode ( Response . self, from: resp. data)
75+ let body = try decode ( Response . self, from: resp. data)
7676 let out = APIError (
7777 response: body,
7878 statusCode: resp. resp. statusCode,
@@ -81,7 +81,24 @@ public struct Client {
8181 )
8282 return . api( out)
8383 } 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> " )
85102 }
86103 }
87104}
@@ -119,7 +136,7 @@ public struct FieldValidation: Decodable, Sendable {
119136public enum ClientError : Error {
120137 case api( APIError )
121138 case network( any Error )
122- case unexpectedResponse( Data )
139+ case unexpectedResponse( String )
123140 case encodeFailure( any Error )
124141
125142 public var description : String {
@@ -129,7 +146,7 @@ public enum ClientError: Error {
129146 case let . network( error) :
130147 error. localizedDescription
131148 case let . unexpectedResponse( data) :
132- " Unexpected or non HTTP response: \( data) "
149+ " Unexpected response: \( data) "
133150 case let . encodeFailure( error) :
134151 " Failed to encode body: \( error. localizedDescription) "
135152 }
0 commit comments