[swift][client] validate http status code (#5226)

* [swift][client] validate http status code

* [swift][client] remove spaces in empty lines
This commit is contained in:
Bruno Coelho 2020-02-08 16:33:36 +00:00 committed by GitHub
parent 9126a5636f
commit 4208f3da82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 280 additions and 353 deletions

View File

@ -173,6 +173,12 @@ extension KeyedDecodingContainerProtocol {
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}
{{#usePromiseKit}}extension RequestBuilder {
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func execute() -> Promise<Response<T>> {
let deferred = Promise<Response<T>>.pending()

View File

@ -25,6 +25,7 @@ protocol JSONEncodable {
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -181,20 +181,25 @@ private var urlSessionStore = SynchronizedDictionary<String, URLSession>()
}
fileprivate func processRequestResponse(urlRequest: URLRequest, data: Data?, response: URLResponse?, error: Error?, completion: @escaping (_ result: Result<Response<T>, Error>) -> Void) {
guard let httpResponse = response as? HTTPURLResponse else {
completion(.failure(ErrorResponse.error(-2, nil, DecodableRequestBuilderError.nilHTTPResponse)))
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ private var urlSessionStore = SynchronizedDictionary<String, URLSession>()
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -323,44 +318,34 @@ private var urlSessionStore = SynchronizedDictionary<String, URLSession>()
completion(.failure(ErrorResponse.error(-2, nil, DecodableRequestBuilderError.nilHTTPResponse)))
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ internal enum DownloadException: Error {
internal enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ internal class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ internal class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ internal class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionReques
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -173,6 +173,12 @@ extension KeyedDecodingContainerProtocol {
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}
extension RequestBuilder {
public func execute() -> Promise<Response<T>> {
let deferred = Promise<Response<T>>.pending()

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return

View File

@ -171,3 +171,9 @@ extension KeyedDecodingContainerProtocol {
}
}
extension HTTPURLResponse {
var isStatusCodeSuccessful: Bool {
return Array(200 ..< 300).contains(statusCode)
}
}

View File

@ -25,6 +25,7 @@ public enum DownloadException: Error {
public enum DecodableRequestBuilderError: Error {
case emptyDataResponse
case nilHTTPResponse
case unsuccessfulHTTPStatusCode(Error?)
case jsonDecoding(DecodingError)
case generalError(Error)
}

View File

@ -187,14 +187,19 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
@ -236,20 +241,10 @@ open class URLSessionRequestBuilder<T>: RequestBuilder<T> {
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
}
@ -324,43 +319,33 @@ open class URLSessionDecodableRequestBuilder<T: Decodable>: URLSessionRequestBui
return
}
guard httpResponse.isStatusCodeSuccessful else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, DecodableRequestBuilderError.unsuccessfulHTTPStatusCode(error))))
return
}
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
switch T.self {
case is String.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
let body = data.flatMap { String(data: $0, encoding: .utf8) } ?? ""
completion(.success(Response<T>(response: httpResponse, body: body as? T)))
case is Void.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: nil)))
case is Data.Type:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
completion(.success(Response(response: httpResponse, body: data as? T)))
default:
if let error = error {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, data, error)))
return
}
guard let data = data, !data.isEmpty else {
completion(.failure(ErrorResponse.error(httpResponse.statusCode, nil, DecodableRequestBuilderError.emptyDataResponse)))
return