@@ -38,31 +38,38 @@ import struct Foundation.URL
3838 /// The middlewares to be invoked before the transport.
3939 public var middlewares : [ any ClientMiddleware ]
4040
41+ /// An error mapping closure to allow customizing the error thrown by the client.
42+ public var errorMapper : ( @Sendable ( ClientError ) -> any Error ) ?
43+
4144 /// Internal initializer that takes an initialized `Converter`.
4245 internal init (
4346 serverURL: URL ,
4447 converter: Converter ,
4548 transport: any ClientTransport ,
46- middlewares: [ any ClientMiddleware ]
49+ middlewares: [ any ClientMiddleware ] ,
50+ errorMapper: ( @Sendable ( ClientError ) -> any Error ) ?
4751 ) {
4852 self . serverURL = serverURL
4953 self . converter = converter
5054 self . transport = transport
5155 self . middlewares = middlewares
56+ self . errorMapper = errorMapper
5257 }
5358
5459 /// Creates a new client.
5560 public init (
5661 serverURL: URL = . defaultOpenAPIServerURL,
5762 configuration: Configuration = . init( ) ,
5863 transport: any ClientTransport ,
59- middlewares: [ any ClientMiddleware ] = [ ]
64+ middlewares: [ any ClientMiddleware ] = [ ] ,
65+ errorMapper: ( @Sendable ( ClientError ) -> any Error ) ? = nil
6066 ) {
6167 self . init (
6268 serverURL: serverURL,
6369 converter: Converter ( configuration: configuration) ,
6470 transport: transport,
65- middlewares: middlewares
71+ middlewares: middlewares,
72+ errorMapper: errorMapper
6673 )
6774 }
6875
@@ -135,57 +142,65 @@ import struct Foundation.URL
135142 underlyingError: underlyingError
136143 )
137144 }
138- let ( request, requestBody) : ( HTTPRequest , HTTPBody ? ) = try await wrappingErrors {
139- try serializer ( input)
140- } mapError: { error in
141- makeError ( error: error)
142- }
143- var next : @Sendable ( HTTPRequest, HTTPBody? , URL) async throws -> ( HTTPResponse , HTTPBody ? ) = {
144- ( _request, _body, _url) in
145- try await wrappingErrors {
146- try await transport. send ( _request, body: _body, baseURL: _url, operationID: operationID)
145+ do {
146+ let ( request, requestBody) : ( HTTPRequest , HTTPBody ? ) = try await wrappingErrors {
147+ try serializer ( input)
147148 } mapError: { error in
148- makeError (
149- request: request,
150- requestBody: requestBody,
151- baseURL: baseURL,
152- error: RuntimeError . transportFailed ( error)
153- )
149+ makeError ( error: error)
154150 }
155- }
156- for middleware in middlewares. reversed ( ) {
157- let tmp = next
158- next = { ( _request, _body, _url) in
151+ var next : @Sendable ( HTTPRequest, HTTPBody? , URL) async throws -> ( HTTPResponse , HTTPBody ? ) = {
152+ ( _request, _body, _url) in
159153 try await wrappingErrors {
160- try await middleware. intercept (
161- _request,
162- body: _body,
163- baseURL: _url,
164- operationID: operationID,
165- next: tmp
166- )
154+ try await transport. send ( _request, body: _body, baseURL: _url, operationID: operationID)
167155 } mapError: { error in
168156 makeError (
169157 request: request,
170158 requestBody: requestBody,
171159 baseURL: baseURL,
172- error: RuntimeError . middlewareFailed ( middlewareType : type ( of : middleware ) , error)
160+ error: RuntimeError . transportFailed ( error)
173161 )
174162 }
175163 }
176- }
177- let ( response, responseBody) : ( HTTPResponse , HTTPBody ? ) = try await next ( request, requestBody, baseURL)
178- return try await wrappingErrors {
179- try await deserializer ( response, responseBody)
180- } mapError: { error in
181- makeError (
182- request: request,
183- requestBody: requestBody,
184- baseURL: baseURL,
185- response: response,
186- responseBody: responseBody,
187- error: error
188- )
164+ for middleware in middlewares. reversed ( ) {
165+ let tmp = next
166+ next = { ( _request, _body, _url) in
167+ try await wrappingErrors {
168+ try await middleware. intercept (
169+ _request,
170+ body: _body,
171+ baseURL: _url,
172+ operationID: operationID,
173+ next: tmp
174+ )
175+ } mapError: { error in
176+ makeError (
177+ request: request,
178+ requestBody: requestBody,
179+ baseURL: baseURL,
180+ error: RuntimeError . middlewareFailed ( middlewareType: type ( of: middleware) , error)
181+ )
182+ }
183+ }
184+ }
185+ let ( response, responseBody) : ( HTTPResponse , HTTPBody ? ) = try await next ( request, requestBody, baseURL)
186+ return try await wrappingErrors {
187+ try await deserializer ( response, responseBody)
188+ } mapError: { error in
189+ makeError (
190+ request: request,
191+ requestBody: requestBody,
192+ baseURL: baseURL,
193+ response: response,
194+ responseBody: responseBody,
195+ error: error
196+ )
197+ }
198+ } catch {
199+ if let errorMapper, let clientError = error as? ClientError {
200+ throw errorMapper ( clientError)
201+ } else {
202+ throw error
203+ }
189204 }
190205 }
191206}
0 commit comments