diff --git a/docs/faq-generators.md b/docs/faq-generators.md index 162c94e8eaa..7a69dd8723a 100644 --- a/docs/faq-generators.md +++ b/docs/faq-generators.md @@ -350,7 +350,14 @@ First you implement the `OpenAPIInterceptor` protocol. public class BearerOpenAPIInterceptor: OpenAPIInterceptor { public init() {} - public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, completion: @escaping (Result) -> Void) { + public func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) { + + guard requestBuilder.requiresAuthentication else { + // no authentication required + completion(.success(urlRequest)) + return + } + refreshTokenIfDoesntExist { token in // Change the current url request @@ -358,13 +365,13 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor { newUrlRequest.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization") // Change the global headers - openAPIClient.customHeaders["Authorization"] = "Bearer \(token)" + requestBuilder.openAPIClient.customHeaders["Authorization"] = "Bearer \(token)" completion(.success(newUrlRequest)) } } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, openAPIClient: OpenAPIClient, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { // We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request refreshTokenIfUnauthorizedRequestResponse( data: data, @@ -375,7 +382,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor { if wasTokenRefreshed, let newToken = newToken { // Change the global headers - openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)" + requestBuilder.openAPIClient.customHeaders["Authorization"] = "Bearer \(newToken)" completion(.retry) } else { @@ -397,7 +404,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor { } } - func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) { + func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error, completionHandler: @escaping (Bool, String?) -> Void) { if let response = response as? HTTPURLResponse, response.statusCode == 401 { startRefreshingToken { token in completionHandler(true, token) diff --git a/modules/openapi-generator/src/main/resources/swift6/libraries/urlsession/URLSessionImplementations.mustache b/modules/openapi-generator/src/main/resources/swift6/libraries/urlsession/URLSessionImplementations.mustache index 9f4a6c1dbbe..c18348ece8c 100644 --- a/modules/openapi-generator/src/main/resources/swift6/libraries/urlsession/URLSessionImplementations.mustache +++ b/modules/openapi-generator/src/main/resources/swift6/libraries/urlsession/URLSessionImplementations.mustache @@ -155,24 +155,48 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}open{{/nonPublicApi}} class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ fileprivate class URLSessionRequestBuilderConfiguration: @unchecked Sendable { case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ extension JSONDataEncoding: ParameterEncoding {} {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } {{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ extension JSONDataEncoding: ParameterEncoding {} completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/asyncAwaitLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/combineDeferredLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/combineLibrary/Sources/CombineLibrary/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/default/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/objcCompatible/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/oneOf/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/promisekitLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 24a6f7f97c5..417854307c5 100644 --- a/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/resultLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ internal class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendab switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ internal class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendab } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ internal class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendab } internal class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ internal class URLSessionDecodableRequestBuilder: URLSessionReques completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ internal class URLSessionDecodableRequestBuilder: URLSessionReques if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ internal class URLSessionDecodableRequestBuilder: URLSessionReques case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ internal enum OpenAPIInterceptorRetry { internal protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } internal class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ internal class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/rxswiftLibrary/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/Sources/PetstoreClient/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } } diff --git a/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift b/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift index 248ae7a8e10..c190c251663 100644 --- a/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift +++ b/samples/client/petstore/swift6/urlsessionLibrary/SwaggerClientTests/SwaggerClient/BearerTokenHandler.swift @@ -33,7 +33,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor { } } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { // We will analyse the response to see if it's a 401, and if it's a 401, we will refresh the token and retry the request refreshTokenIfUnauthorizedRequestResponse( data: data, @@ -66,7 +66,7 @@ public class BearerOpenAPIInterceptor: OpenAPIInterceptor { } } - func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse, error: Error, completionHandler: @escaping (Bool, String?) -> Void) { + func refreshTokenIfUnauthorizedRequestResponse(data: Data?, response: URLResponse?, error: Error, completionHandler: @escaping (Bool, String?) -> Void) { if let response = response as? HTTPURLResponse, response.statusCode == 401 { startRefreshingToken { token in completionHandler(true, token) diff --git a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift index 7ddb8d06632..42714671076 100644 --- a/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift +++ b/samples/client/petstore/swift6/validation/PetstoreClient/Classes/OpenAPIs/Infrastructure/URLSessionImplementations.swift @@ -155,24 +155,48 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { switch result { case .success(let modifiedRequest): let dataTask = urlSession.dataTaskFromProtocol(with: modifiedRequest) { data, response, error in - self.cleanupRequest() - if let response, let error { - self.openAPIClient.interceptor.retry(urlRequest: modifiedRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in - switch retry { - case .retry: - self.execute(completion: completion) + self.cleanupRequest() - case .dontRetry: - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } - } - } - } else { - self.openAPIClient.apiResponseQueue.async { - self.processRequestResponse(urlRequest: request, data: data, response: response, error: error, completion: completion) - } + if let error = error { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -1, + data: data, + response: response, + error: error, + completion: completion + ) + return } + + guard let httpResponse = response as? HTTPURLResponse else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: -2, + data: data, + response: response, + error: DecodableRequestBuilderError.nilHTTPResponse, + completion: completion + ) + return + } + + guard self.openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { + self.retryRequest( + urlRequest: modifiedRequest, + urlSession: urlSession, + statusCode: httpResponse.statusCode, + data: data, + response: httpResponse, + error: DecodableRequestBuilderError.unsuccessfulHTTPStatusCode, + completion: completion + ) + return + } + + self.processRequestResponse(urlRequest: request, data: data, httpResponse: httpResponse, error: error, completion: completion) } self.onProgressReady?(dataTask.progress) @@ -204,22 +228,21 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } } - fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + private func retryRequest(urlRequest: URLRequest, urlSession: URLSessionProtocol, statusCode: Int, data: Data?, response: URLResponse?, error: Error, completion: @Sendable @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { + self.openAPIClient.interceptor.retry(urlRequest: urlRequest, urlSession: urlSession, requestBuilder: self, data: data, response: response, error: error) { retry in + switch retry { + case .retry: + self.execute(completion: completion) - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return + case .dontRetry: + self.openAPIClient.apiResponseQueue.async { + completion(.failure(ErrorResponse.error(statusCode, data, response, error))) + } + } } + } - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is Void.Type: @@ -297,22 +320,7 @@ open class URLSessionRequestBuilder: RequestBuilder, @unchecked Sendable { } open class URLSessionDecodableRequestBuilder: URLSessionRequestBuilder, @unchecked Sendable { - override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { - - if let error = error { - completion(.failure(ErrorResponse.error(-1, data, response, error))) - return - } - - guard let httpResponse = response as? HTTPURLResponse else { - completion(.failure(ErrorResponse.error(-2, data, response, DecodableRequestBuilderError.nilHTTPResponse))) - return - } - - guard openAPIClient.successfulStatusCodeRange.contains(httpResponse.statusCode) else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, response, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode))) - return - } + override fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, httpResponse: HTTPURLResponse, error: Error?, completion: @escaping (_ result: Swift.Result, ErrorResponse>) -> Void) { switch T.self { case is String.Type: @@ -353,9 +361,9 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui completion(.success(Response(response: httpResponse, body: filePath as! T, bodyData: data))) } catch let requestParserError as DownloadException { - completion(.failure(ErrorResponse.error(400, data, response, requestParserError))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, requestParserError))) } catch { - completion(.failure(ErrorResponse.error(400, data, response, error))) + completion(.failure(ErrorResponse.error(400, data, httpResponse, error))) } case is Void.Type: @@ -372,7 +380,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui if let expressibleByNilLiteralType = T.self as? ExpressibleByNilLiteral.Type { completion(.success(Response(response: httpResponse, body: expressibleByNilLiteralType.init(nilLiteral: ()) as! T, bodyData: data))) } else { - completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, response, DecodableRequestBuilderError.emptyDataResponse))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, httpResponse, DecodableRequestBuilderError.emptyDataResponse))) } return } @@ -383,7 +391,7 @@ open class URLSessionDecodableRequestBuilder: URLSessionRequestBui case let .success(decodableObj): completion(.success(Response(response: httpResponse, body: decodableObj, bodyData: unwrappedData))) case let .failure(error): - completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, response, error))) + completion(.failure(ErrorResponse.error(httpResponse.statusCode, unwrappedData, httpResponse, error))) } } } @@ -694,7 +702,7 @@ public enum OpenAPIInterceptorRetry { public protocol OpenAPIInterceptor { func intercept(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, completion: @escaping (Result) -> Void) - func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) + func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) } public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { @@ -704,7 +712,7 @@ public class DefaultOpenAPIInterceptor: OpenAPIInterceptor { completion(.success(urlRequest)) } - public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { + public func retry(urlRequest: URLRequest, urlSession: URLSessionProtocol, requestBuilder: RequestBuilder, data: Data?, response: URLResponse?, error: Error, completion: @escaping (OpenAPIInterceptorRetry) -> Void) { completion(.dontRetry) } }