From 0977510e1f64f0a88fdff951e3baaacdd399cd41 Mon Sep 17 00:00:00 2001 From: Max Radermacher Date: Tue, 25 Nov 2025 09:32:58 -0600 Subject: [PATCH] Throw OWSHTTPError for unexpected status codes --- Signal/Calls/CallLinkManager.swift | 6 +-- Signal/Emoji/EmojiPickerCollectionView.swift | 4 +- ...questAccountDataReportViewController.swift | 12 ++---- .../Linked Devices/LinkedDevicesView.swift | 2 +- .../Contacts/AccountChecker.swift | 2 +- .../Devices/OWSDeviceService.swift | 40 +++++-------------- .../Messages/OWSIdentityManager.swift | 2 +- .../API/Requests/WhoAmI/WhoAmIManager.swift | 8 +--- .../Backups/BackupSubscriptionManager.swift | 10 +---- .../Donations/Stripe+Subscriptions.swift | 6 +-- ...bscriptionRedemptionNecessityChecker.swift | 5 +-- .../Upload/UploadEndpointCDN2.swift | 2 +- .../Usernames/UsernameApiClientImpl.swift | 12 +++--- .../InactiveLinkedDeviceFinderTest.swift | 2 +- 14 files changed, 36 insertions(+), 77 deletions(-) diff --git a/Signal/Calls/CallLinkManager.swift b/Signal/Calls/CallLinkManager.swift index 15b797f0cb..8242410f8f 100644 --- a/Signal/Calls/CallLinkManager.swift +++ b/Signal/Calls/CallLinkManager.swift @@ -110,10 +110,10 @@ class CallLinkManagerImpl: CallLinkManager { ] ) let httpResult = try await self.networkManager.asyncRequest(httpRequest) - guard httpResult.responseStatusCode == 200, let responseBodyData = httpResult.responseBodyData else { - throw OWSGenericError("Couldn't handle successful result from the server.") + guard httpResult.responseStatusCode == 200 else { + throw httpResult.asError() } - let httpResponse = try JSONDecoder().decode(CallLinkCreateAuthResponse.self, from: responseBodyData) + let httpResponse = try JSONDecoder().decode(CallLinkCreateAuthResponse.self, from: httpResult.responseBodyData ?? Data()) let credentialResponse = try CreateCallLinkCredentialResponse(contents: httpResponse.credential) return try credentialRequestContext.receive(credentialResponse, userId: localAci, params: self.serverParams) } diff --git a/Signal/Emoji/EmojiPickerCollectionView.swift b/Signal/Emoji/EmojiPickerCollectionView.swift index ace53de8e6..c768e5b23f 100644 --- a/Signal/Emoji/EmojiPickerCollectionView.swift +++ b/Signal/Emoji/EmojiPickerCollectionView.swift @@ -594,7 +594,7 @@ enum EmojiSearchIndex { let urlSession = signalService.urlSessionForUpdates() let response = try await urlSession.performRequest("/dynamic/android/emoji/search/manifest.json", method: .get) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("bad response code for emoji manifest fetch") + throw response.asError() } let manifest = try JSONDecoder().decode(Manifest.self, from: response.responseBodyData ?? Data()) @@ -673,7 +673,7 @@ enum EmojiSearchIndex { method: .get, ) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Bad response code for emoji index fetch") + throw response.asError() } var searchIndex = [String: [String]]() for emojiTags in try JSONDecoder().decode([EmojiTags].self, from: response.responseBodyData ?? Data()) { diff --git a/Signal/src/ViewControllers/AppSettings/Account/RequestAccountDataReportViewController.swift b/Signal/src/ViewControllers/AppSettings/Account/RequestAccountDataReportViewController.swift index 21ecd6802b..10efbd7602 100644 --- a/Signal/src/ViewControllers/AppSettings/Account/RequestAccountDataReportViewController.swift +++ b/Signal/src/ViewControllers/AppSettings/Account/RequestAccountDataReportViewController.swift @@ -170,16 +170,10 @@ class RequestAccountDataReportViewController: OWSTableViewController2 { asyncBlock: { modal in do { let response = try await SSKEnvironment.shared.networkManagerRef.asyncRequest(request) - let status = response.responseStatusCode - guard status == 200 else { - throw OWSGenericError("Received a \(status) status code. The request failed") - } - guard let rawData = response.responseBodyData else { - throw OWSGenericError("Received an empty response") - } - guard let report = try? AccountDataReport(rawData: rawData) else { - throw OWSGenericError("Couldn't parse account data report, presumably due to a bug") + guard response.responseStatusCode == 200 else { + throw response.asError() } + let report = try AccountDataReport(rawData: response.responseBodyData ?? Data()) modal.dismissIfNotCanceled(completionIfNotCanceled: { [weak self] in self?.confirmExport { self?.didConfirmExport(of: report) diff --git a/Signal/src/ViewControllers/AppSettings/Linked Devices/LinkedDevicesView.swift b/Signal/src/ViewControllers/AppSettings/Linked Devices/LinkedDevicesView.swift index a605b0d4ab..03438c7257 100644 --- a/Signal/src/ViewControllers/AppSettings/Linked Devices/LinkedDevicesView.swift +++ b/Signal/src/ViewControllers/AppSettings/Linked Devices/LinkedDevicesView.swift @@ -198,7 +198,7 @@ class LinkedDevicesViewModel: ObservableObject { func renameDevice( _ displayableDevice: DisplayableDevice, to newName: String - ) async throws(OWSDeviceRenameError) { + ) async throws { try await deviceService.renameDevice( device: displayableDevice.device, newName: newName, diff --git a/SignalServiceKit/Contacts/AccountChecker.swift b/SignalServiceKit/Contacts/AccountChecker.swift index ebf946e41c..6a4e3669bd 100644 --- a/SignalServiceKit/Contacts/AccountChecker.swift +++ b/SignalServiceKit/Contacts/AccountChecker.swift @@ -49,7 +49,7 @@ public class AccountChecker { do { let response = try await networkManager.asyncRequest(accountRequest) guard response.responseStatusCode == 200 else { - throw OWSGenericError("Unexpected server response.") + throw response.asError() } await db.awaitableWrite { tx in var recipient = recipientFetcher.fetchOrCreate(serviceId: serviceId, tx: tx) diff --git a/SignalServiceKit/Devices/OWSDeviceService.swift b/SignalServiceKit/Devices/OWSDeviceService.swift index 57ba915e29..3963feee68 100644 --- a/SignalServiceKit/Devices/OWSDeviceService.swift +++ b/SignalServiceKit/Devices/OWSDeviceService.swift @@ -18,7 +18,7 @@ public protocol OWSDeviceService { func renameDevice( device: OWSDevice, newName: String, - ) async throws(OWSDeviceRenameError) + ) async throws } extension OWSDeviceService { @@ -31,12 +31,6 @@ extension OWSDeviceService { } } -public enum OWSDeviceRenameError: Error { - case encryptionFailed - case networkError - case assertion -} - // MARK: - struct OWSDeviceServiceImpl: OWSDeviceService { @@ -210,36 +204,24 @@ struct OWSDeviceServiceImpl: OWSDeviceService { func renameDevice( device: OWSDevice, newName: String, - ) async throws(OWSDeviceRenameError) { + ) async throws { guard let identityKeyPair = db.read(block: { tx in identityManager.identityKeyPair(for: .aci, tx: tx) }) else { - throw .encryptionFailed + throw OWSAssertionError("can't rename device without identity key") } - let newNameEncrypted: String - do { - newNameEncrypted = try OWSDeviceNames.encryptDeviceName( - plaintext: newName, - identityKeyPair: identityKeyPair.keyPair - ).base64EncodedString() - } catch { - owsFailDebug("Failed to encrypt device name! \(error)") - throw .encryptionFailed - } + let newNameEncrypted = try OWSDeviceNames.encryptDeviceName( + plaintext: newName, + identityKeyPair: identityKeyPair.keyPair + ).base64EncodedString() - let response: HTTPResponse - do { - response = try await self.networkManager.asyncRequest( - .renameDevice(device: device, encryptedName: newNameEncrypted) - ) - } catch { - throw .networkError - } + let response = try await self.networkManager.asyncRequest( + .renameDevice(device: device, encryptedName: newNameEncrypted) + ) guard response.responseStatusCode == 204 else { - owsFailDebug("Unexpected response status code! \(response.responseStatusCode)") - throw OWSDeviceRenameError.assertion + throw response.asError() } await db.awaitableWrite { tx in diff --git a/SignalServiceKit/Messages/OWSIdentityManager.swift b/SignalServiceKit/Messages/OWSIdentityManager.swift index 78ba1c3613..c46001bd6a 100644 --- a/SignalServiceKit/Messages/OWSIdentityManager.swift +++ b/SignalServiceKit/Messages/OWSIdentityManager.swift @@ -1022,7 +1022,7 @@ public class OWSIdentityManagerImpl: OWSIdentityManager { let response = try await self.networkManager.asyncRequest(request) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Unexpected response from batch identity request \(response.responseStatusCode)") + throw response.asError() } guard let responseDictionary = response.responseBodyDict else { diff --git a/SignalServiceKit/Network/API/Requests/WhoAmI/WhoAmIManager.swift b/SignalServiceKit/Network/API/Requests/WhoAmI/WhoAmIManager.swift index a8258ec4d9..da7b9a093d 100644 --- a/SignalServiceKit/Network/API/Requests/WhoAmI/WhoAmIManager.swift +++ b/SignalServiceKit/Network/API/Requests/WhoAmI/WhoAmIManager.swift @@ -25,15 +25,11 @@ struct WhoAmIManagerImpl: WhoAmIManager { ) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Unexpected status code from WhoAmI! \(response.responseStatusCode)") - } - - guard let bodyData = response.responseBodyData else { - throw OWSAssertionError("Missing response body data from WhoAmI!") + throw response.asError() } do { - return try JSONDecoder().decode(WhoAmIResponse.self, from: bodyData) + return try JSONDecoder().decode(WhoAmIResponse.self, from: response.responseBodyData ?? Data()) } catch { throw OWSAssertionError("Failed to parse WhoAmI response! \(error)") } diff --git a/SignalServiceKit/Subscriptions/Backups/BackupSubscriptionManager.swift b/SignalServiceKit/Subscriptions/Backups/BackupSubscriptionManager.swift index e4a54fbb94..5b3fe025f9 100644 --- a/SignalServiceKit/Subscriptions/Backups/BackupSubscriptionManager.swift +++ b/SignalServiceKit/Subscriptions/Backups/BackupSubscriptionManager.swift @@ -765,10 +765,7 @@ final class BackupSubscriptionManagerImpl: BackupSubscriptionManager { ) guard registerSubscriberIdResponse.responseStatusCode == 200 else { - throw OWSAssertionError( - "Unexpected status code registering new Backup subscriber ID! \(registerSubscriberIdResponse.responseStatusCode)", - logger: logger - ) + throw registerSubscriberIdResponse.asError() } /// Next, we tell the server (unauthenticated) to associate the @@ -784,10 +781,7 @@ final class BackupSubscriptionManagerImpl: BackupSubscriptionManager { ) guard associateIdsResponse.responseStatusCode == 200 else { - throw OWSAssertionError( - "Unexpected status code associating new Backup subscriber ID with originalTransactionId! \(associateIdsResponse.responseStatusCode)", - logger: logger - ) + throw associateIdsResponse.asError() } let newSubscriberData = IAPSubscriberData( diff --git a/SignalServiceKit/Subscriptions/Donations/Stripe+Subscriptions.swift b/SignalServiceKit/Subscriptions/Donations/Stripe+Subscriptions.swift index d4c3016164..bd4aa9f47b 100644 --- a/SignalServiceKit/Subscriptions/Donations/Stripe+Subscriptions.swift +++ b/SignalServiceKit/Subscriptions/Donations/Stripe+Subscriptions.swift @@ -17,10 +17,8 @@ extension Stripe { let response = try await SSKEnvironment.shared.networkManagerRef .asyncRequest(request, retryPolicy: .hopefullyRecoverable) - let statusCode = response.responseStatusCode - - guard statusCode == 200 else { - throw OWSAssertionError("Got bad response code \(statusCode).") + guard response.responseStatusCode == 200 else { + throw response.asError() } guard let parser = response.responseBodyParamParser else { diff --git a/SignalServiceKit/Subscriptions/SubscriptionRedemptionNecessityChecker.swift b/SignalServiceKit/Subscriptions/SubscriptionRedemptionNecessityChecker.swift index 61b33b9799..6e004047f3 100644 --- a/SignalServiceKit/Subscriptions/SubscriptionRedemptionNecessityChecker.swift +++ b/SignalServiceKit/Subscriptions/SubscriptionRedemptionNecessityChecker.swift @@ -232,10 +232,7 @@ struct SubscriptionRedemptionNecessityChecker { ) guard registerSubscriberIdResponse.responseStatusCode == 200 else { - throw OWSAssertionError( - "Unexpected status code registering new Backup subscriber ID! \(registerSubscriberIdResponse.responseStatusCode)", - logger: logger - ) + throw registerSubscriberIdResponse.asError() } } } diff --git a/SignalServiceKit/Upload/UploadEndpointCDN2.swift b/SignalServiceKit/Upload/UploadEndpointCDN2.swift index 11c0563fb6..b8cdc2f765 100644 --- a/SignalServiceKit/Upload/UploadEndpointCDN2.swift +++ b/SignalServiceKit/Upload/UploadEndpointCDN2.swift @@ -61,7 +61,7 @@ struct UploadEndpointCDN2: UploadEndpoint { ) guard response.responseStatusCode == 201 else { - throw OWSAssertionError("Invalid statusCode: \(response.responseStatusCode).") + throw response.asError() } guard let locationHeader = response.headers["location"], diff --git a/SignalServiceKit/Usernames/UsernameApiClientImpl.swift b/SignalServiceKit/Usernames/UsernameApiClientImpl.swift index a78d225dd4..d66b744432 100644 --- a/SignalServiceKit/Usernames/UsernameApiClientImpl.swift +++ b/SignalServiceKit/Usernames/UsernameApiClientImpl.swift @@ -31,9 +31,7 @@ public class UsernameApiClientImpl: UsernameApiClient { let response = try await performRequest(request: request) guard response.responseStatusCode == 200 else { - throw OWSAssertionError( - "Unexpected status code from successful request: \(response.responseStatusCode)" - ) + throw response.asError() } guard let parser = response.responseBodyParamParser else { @@ -97,7 +95,7 @@ public class UsernameApiClientImpl: UsernameApiClient { let response = try await performRequest(request: request) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Unexpected status code from successful request: \(response.responseStatusCode)") + throw response.asError() } guard let parser = response.responseBodyParamParser else { @@ -139,7 +137,7 @@ public class UsernameApiClientImpl: UsernameApiClient { let request = OWSRequestFactory.deleteExistingUsernameRequest() let response = try await performRequest(request: request) guard response.responseStatusCode == 204 else { - throw OWSAssertionError("Unexpected status code from successful request: \(response.responseStatusCode)") + throw response.asError() } } @@ -167,7 +165,7 @@ public class UsernameApiClientImpl: UsernameApiClient { let response = try await performRequest(request: request) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Unexpected response code: \(response.responseStatusCode)") + throw response.asError() } guard let parser = response.responseBodyParamParser else { @@ -184,7 +182,7 @@ public class UsernameApiClientImpl: UsernameApiClient { let response = try await performRequest(request: request) guard response.responseStatusCode == 200 else { - throw OWSAssertionError("Unexpected response code: \(response.responseStatusCode)") + throw response.asError() } guard let parser = response.responseBodyParamParser else { diff --git a/SignalServiceKit/tests/Devices/InactiveLinkedDeviceFinderTest.swift b/SignalServiceKit/tests/Devices/InactiveLinkedDeviceFinderTest.swift index d92e6ca253..fc4803c3e2 100644 --- a/SignalServiceKit/tests/Devices/InactiveLinkedDeviceFinderTest.swift +++ b/SignalServiceKit/tests/Devices/InactiveLinkedDeviceFinderTest.swift @@ -183,5 +183,5 @@ private class MockDevicesService: OWSDeviceService { func unlinkDevice(deviceId: DeviceId) async throws {} - func renameDevice(device: OWSDevice, newName: String) async throws(OWSDeviceRenameError) {} + func renameDevice(device: OWSDevice, newName: String) async throws {} }