diff --git a/Sources/Auth/Internal/APIClient.swift b/Sources/Auth/Internal/APIClient.swift index 4f866529..d6867f7c 100644 --- a/Sources/Auth/Internal/APIClient.swift +++ b/Sources/Auth/Internal/APIClient.swift @@ -33,11 +33,14 @@ struct APIClient: Sendable { /// There are some GoTrue endpoints that can return a `PostgrestError`, for example the /// ``AuthAdmin/deleteUser(id:shouldSoftDelete:)`` that could return an error in case the /// user is referenced by other schemas. - let postgrestError = try configuration.decoder.decode( + if let postgrestError = try? configuration.decoder.decode( PostgrestError.self, from: response.data - ) - throw postgrestError + ) { + throw postgrestError + } + + throw HTTPError(data: response.data, response: response.response) } return response diff --git a/Sources/PostgREST/PostgrestBuilder.swift b/Sources/PostgREST/PostgrestBuilder.swift index ac15ec6e..fa19f486 100644 --- a/Sources/PostgREST/PostgrestBuilder.swift +++ b/Sources/PostgREST/PostgrestBuilder.swift @@ -110,8 +110,11 @@ public class PostgrestBuilder: @unchecked Sendable { let response = try await http.fetch(request, baseURL: configuration.url) guard 200 ..< 300 ~= response.statusCode else { - let error = try configuration.decoder.decode(PostgrestError.self, from: response.data) - throw error + if let error = try? configuration.decoder.decode(PostgrestError.self, from: response.data) { + throw error + } + + throw HTTPError(data: response.data, response: response.response) } let value = try decode(response.data) diff --git a/Sources/Storage/StorageApi.swift b/Sources/Storage/StorageApi.swift index 5f21ee79..cb9c8a94 100644 --- a/Sources/Storage/StorageApi.swift +++ b/Sources/Storage/StorageApi.swift @@ -33,8 +33,11 @@ public class StorageApi: @unchecked Sendable { let response = try await http.rawFetch(request) guard (200 ..< 300).contains(response.statusCode) else { - let error = try configuration.decoder.decode(StorageError.self, from: response.data) - throw error + if let error = try? configuration.decoder.decode(StorageError.self, from: response.data) { + throw error + } + + throw HTTPError(data: response.data, response: response.response) } return response diff --git a/Sources/_Helpers/SharedModels/HTTPError.swift b/Sources/_Helpers/SharedModels/HTTPError.swift new file mode 100644 index 00000000..bc78c889 --- /dev/null +++ b/Sources/_Helpers/SharedModels/HTTPError.swift @@ -0,0 +1,25 @@ +// +// HTTPError.swift +// +// +// Created by Guilherme Souza on 07/05/24. +// + +import Foundation + +#if canImport(FoundationNetworking) + import FoundationNetworking +#endif + +/// A generic error from a HTTP request. +/// +/// Contains both the `Data` and `HTTPURLResponse` which you can use to extract more information about it. +public struct HTTPError: Error, Sendable { + public let data: Data + public let response: HTTPURLResponse + + public init(data: Data, response: HTTPURLResponse) { + self.data = data + self.response = response + } +}