diff --git a/RadixWallet/Clients/HTTPClient/HTTPClient+Interface.swift b/RadixWallet/Clients/HTTPClient/HTTPClient+Interface.swift index 866a50b1a5..046fd1b36a 100644 --- a/RadixWallet/Clients/HTTPClient/HTTPClient+Interface.swift +++ b/RadixWallet/Clients/HTTPClient/HTTPClient+Interface.swift @@ -5,5 +5,11 @@ public struct HTTPClient: Sendable, DependencyKey { // MARK: HTTPClient.ExecuteRequest extension HTTPClient { - public typealias ExecuteRequest = @Sendable (URLRequest) async throws -> Data + public typealias ExecuteRequest = @Sendable (_ request: URLRequest, _ acceptedStatusCodes: [HTTPStatusCode]) async throws -> Data +} + +extension HTTPClient { + func executeRequest(_ request: URLRequest) async throws -> Data { + try await executeRequest(request, [.ok]) + } } diff --git a/RadixWallet/Clients/HTTPClient/HTTPClient+Live.swift b/RadixWallet/Clients/HTTPClient/HTTPClient+Live.swift index 6dcd4b22b5..fb9e79ba01 100644 --- a/RadixWallet/Clients/HTTPClient/HTTPClient+Live.swift +++ b/RadixWallet/Clients/HTTPClient/HTTPClient+Live.swift @@ -3,14 +3,14 @@ extension HTTPClient { let session = URLSession.shared return .init( - executeRequest: { request in + executeRequest: { request, acceptedStatusCodes in let (data, urlResponse) = try await session.data(for: request) guard let httpURLResponse = urlResponse as? HTTPURLResponse else { throw ExpectedHTTPURLResponse() } - guard httpURLResponse.statusCode == BadHTTPResponseCode.expected else { + guard let statusCode = httpURLResponse.status, acceptedStatusCodes.contains(statusCode) else { #if DEBUG loggerGlobal.error("Request with URL: \(request.url!.absoluteString) failed with status code: \(httpURLResponse.statusCode), data: \(data.prettyPrintedJSONString ?? "")") #endif diff --git a/RadixWallet/Clients/HTTPClient/HTTPClient+Mock.swift b/RadixWallet/Clients/HTTPClient/HTTPClient+Mock.swift index aa89236ee5..10e1b740ff 100644 --- a/RadixWallet/Clients/HTTPClient/HTTPClient+Mock.swift +++ b/RadixWallet/Clients/HTTPClient/HTTPClient+Mock.swift @@ -8,7 +8,7 @@ extension HTTPClient: TestDependencyKey { private static func noop() -> Self { .init( - executeRequest: { _ in Data() } + executeRequest: { _, _ in Data() } ) } } diff --git a/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift b/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift index cb02bc64bb..e7dcd762e9 100644 --- a/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift +++ b/RadixWallet/Clients/NPSSurveyClient/NPSSurveyClient+Live.swift @@ -70,11 +70,13 @@ extension NPSSurveyClient { extension NPSSurveyClient { #if DEBUG static let rootURL = "https://dev-wallet-net-promoter-score.radixdlt.com/v1/responses" + static let formUUID = "281622a0-dc6b-11ee-8fd1-23c96056fbd2" #else static let rootURL = "https://wallet-net-promoter-score.radixdlt.com/v1/responses" + static let formUUID = "3432b6e0-dfad-11ee-a53c-95167f067d9c" #endif - enum QueryItem: String { + enum BodyParam: String { case id case formUuid = "form_uuid" case nps @@ -101,8 +103,7 @@ extension NPSSurveyClient { } }() - var urlComponents = URLComponents(string: Self.rootURL)! - urlComponents.queryItems = [.userId(userId), .formUUID] + (feedback.map(\.queryItems) ?? []) + let urlComponents = URLComponents(string: Self.rootURL)! guard let url = urlComponents.url else { return @@ -110,42 +111,27 @@ extension NPSSurveyClient { var urlRequest = URLRequest(url: url) urlRequest.httpMethod = "POST" + urlRequest.allHTTPHeaderFields = [ + "accept": "application/json", + "Content-Type": "application/json", + ] + + var feedbackParams: [String: Any] = [ + BodyParam.id.rawValue: userId.uuidString, + BodyParam.formUuid.rawValue: formUUID, + ] + if let feedback { + feedbackParams[BodyParam.nps.rawValue] = feedback.npsScore + } + if let reason = feedback?.reason { + feedbackParams[BodyParam.feedbackReason.rawValue] = reason + } + urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: feedbackParams) do { - _ = try await httpClient.executeRequest(urlRequest) + _ = try await httpClient.executeRequest(urlRequest, [.ok, .accepted]) } catch { loggerGlobal.info("Failed to submit nps survey feedback \(error)") } } } - -private extension URLQueryItem { - static func userId(_ id: UUID) -> Self { - .init(name: "id", value: id.uuidString) - } - - #if DEBUG - static let formUUID: Self = .init(name: "form_uuid", value: "281622a0-dc6b-11ee-8fd1-23c96056fbd2") - #else - static let formUUID: Self = .init(name: "form_uuid", value: "3432b6e0-dfad-11ee-a53c-95167f067d9c") - #endif - - static func npsScore(_ score: Int) -> Self { - .init(name: NPSSurveyClient.QueryItem.nps.rawValue, value: "\(score)") - } - - static func npsFeedbackReason(_ reason: String) -> Self { - .init(name: NPSSurveyClient.QueryItem.feedbackReason.rawValue, value: reason) - } -} - -extension NPSSurveyClient.UserFeedback { - var queryItems: [URLQueryItem] { - var queryItems: [URLQueryItem] = [] - queryItems.append(.npsScore(npsScore)) - if let reason { - queryItems.append(.npsFeedbackReason(reason)) - } - return queryItems - } -} diff --git a/RadixWallet/Clients/ROLAClient/ROLAClient+Live.swift b/RadixWallet/Clients/ROLAClient/ROLAClient+Live.swift index 015850bba4..df3a96b3a0 100644 --- a/RadixWallet/Clients/ROLAClient/ROLAClient+Live.swift +++ b/RadixWallet/Clients/ROLAClient/ROLAClient+Live.swift @@ -54,7 +54,7 @@ extension ROLAClient { throw ExpectedHTTPURLResponse() } - guard httpURLResponse.statusCode == BadHTTPResponseCode.expected else { + guard httpURLResponse.status == .ok else { throw BadHTTPResponseCode(got: httpURLResponse.statusCode) } diff --git a/RadixWallet/Core/SharedModels/HTTPURLSessionResponse/HTTPURLSessionResponse.swift b/RadixWallet/Core/SharedModels/HTTPURLSessionResponse/HTTPURLSessionResponse.swift index 03113ed69d..020ac5c450 100644 --- a/RadixWallet/Core/SharedModels/HTTPURLSessionResponse/HTTPURLSessionResponse.swift +++ b/RadixWallet/Core/SharedModels/HTTPURLSessionResponse/HTTPURLSessionResponse.swift @@ -6,8 +6,6 @@ public struct ExpectedHTTPURLResponse: Swift.Error { // MARK: - BadHTTPResponseCode public struct BadHTTPResponseCode: LocalizedError { public let got: Int - public let butExpected = Self.expected - public static let expected = 200 public init(got: Int) { self.got = got @@ -33,3 +31,18 @@ public struct ResponseDecodingError: Swift.Error { self.error = error } } + +// MARK: - HTTPStatusCode +public enum HTTPStatusCode: Int, Error { + /// - ok: Standard response for successful HTTP requests. + case ok = 200 + + /// - accepted: The request has been accepted for processing, but the processing has not been completed. + case accepted = 202 +} + +extension HTTPURLResponse { + var status: HTTPStatusCode? { + .init(rawValue: statusCode) + } +}