Clean up ahead of PR.
This commit is contained in:
parent
4db5d5b080
commit
67d9eeab5b
@ -976,8 +976,8 @@ extension CallService: CallManagerDelegate {
|
||||
}.done(on: .main) { response in
|
||||
self.callManager.receivedHttpResponse(
|
||||
requestId: requestId,
|
||||
statusCode: UInt16(response.statusCode),
|
||||
body: response.responseData
|
||||
statusCode: UInt16(response.responseStatusCode),
|
||||
body: response.responseBodyData
|
||||
)
|
||||
}.catch(on: .main) { error in
|
||||
if error.isNetworkFailureOrTimeout {
|
||||
|
||||
@ -119,11 +119,10 @@ fileprivate extension Stripe {
|
||||
firstly(on: .sharedUserInitiated) { () -> Promise<OWSHTTPResponse> in
|
||||
try postForm(endpoint: "tokens", parameters: parameters(for: payment))
|
||||
}.map(on: .sharedUserInitiated) { response in
|
||||
guard let responseData = response.responseData, !responseData.isEmpty else {
|
||||
throw OWSAssertionError("Missing response data")
|
||||
guard let json = response.responseBodyJson else {
|
||||
throw OWSAssertionError("Missing responseBodyJson")
|
||||
}
|
||||
let responseObject = try JSONSerialization.jsonObject(with: responseData, options: .init(rawValue: 0))
|
||||
guard let parser = ParamParser(responseObject: responseObject) else {
|
||||
guard let parser = ParamParser(responseObject: json) else {
|
||||
throw OWSAssertionError("Failed to decode JSON response")
|
||||
}
|
||||
return try parser.required(key: "id")
|
||||
@ -137,11 +136,10 @@ fileprivate extension Stripe {
|
||||
let parameters: [String: Any] = ["card": ["token": tokenId], "type": "card"]
|
||||
return try postForm(endpoint: "payment_methods", parameters: parameters)
|
||||
}.map(on: .sharedUserInitiated) { response in
|
||||
guard let responseData = response.responseData, !responseData.isEmpty else {
|
||||
throw OWSAssertionError("Missing response data")
|
||||
guard let json = response.responseBodyJson else {
|
||||
throw OWSAssertionError("Missing responseBodyJson")
|
||||
}
|
||||
let responseObject = try JSONSerialization.jsonObject(with: responseData, options: .init(rawValue: 0))
|
||||
guard let parser = ParamParser(responseObject: responseObject) else {
|
||||
guard let parser = ParamParser(responseObject: json) else {
|
||||
throw OWSAssertionError("Failed to decode JSON response")
|
||||
}
|
||||
return try parser.required(key: "id")
|
||||
|
||||
@ -209,10 +209,10 @@ class StubbableNetworkManager: NetworkManager {
|
||||
var block: (TSRequest, NetworkManagerSuccess, NetworkManagerFailure) -> Void = { request, success, _ in
|
||||
Logger.info("faking success for request: \(request)")
|
||||
let response = OWSHTTPResponseImpl(requestUrl: request.url!,
|
||||
status: 200,
|
||||
headers: OWSHttpHeaders(),
|
||||
bodyData: nil,
|
||||
message: nil)
|
||||
status: 200,
|
||||
headers: OWSHttpHeaders(),
|
||||
bodyData: nil,
|
||||
message: nil)
|
||||
success(response)
|
||||
}
|
||||
|
||||
|
||||
@ -284,7 +284,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior404: .fail)
|
||||
}.then(on: .global()) { (response: OWSHTTPResponse) -> Promise<UpdatedV2Group> in
|
||||
|
||||
guard let changeActionsProtoData = response.responseData else {
|
||||
guard let changeActionsProtoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
let changeActionsProto = try GroupsV2Protos.parseAndVerifyChangeActionsProto(changeActionsProtoData,
|
||||
@ -490,7 +490,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior404: .fail)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> GroupsProtoAvatarUploadAttributes in
|
||||
|
||||
guard let protoData = response.responseData else {
|
||||
guard let protoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
return try GroupsProtoAvatarUploadAttributes(serializedData: protoData)
|
||||
@ -549,7 +549,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior403: .removeFromGroup,
|
||||
behavior404: .groupDoesNotExistOnService)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> GroupsProtoGroup in
|
||||
guard let groupProtoData = response.responseData else {
|
||||
guard let groupProtoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
return try GroupsProtoGroup(serializedData: groupProtoData)
|
||||
@ -634,7 +634,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior403: .ignore,
|
||||
behavior404: .fail)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> GroupsProtoGroupChanges in
|
||||
guard let groupChangesProtoData = response.responseData else {
|
||||
guard let groupChangesProtoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
return try GroupsProtoGroupChanges(serializedData: groupChangesProtoData)
|
||||
@ -996,9 +996,10 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
headers: request.headers.headers,
|
||||
body: request.bodyData)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> OWSHTTPResponse in
|
||||
let hasValidStatusCode = [200, 206].contains(response.statusCode)
|
||||
let statusCode = response.responseStatusCode
|
||||
let hasValidStatusCode = [200, 206].contains(statusCode)
|
||||
guard hasValidStatusCode else {
|
||||
throw OWSAssertionError("Invalid status code: \(response.statusCode)")
|
||||
throw OWSAssertionError("Invalid status code: \(statusCode)")
|
||||
}
|
||||
|
||||
// NOTE: responseObject may be nil; not all group v2 responses have bodies.
|
||||
@ -1530,7 +1531,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior403: behavior403,
|
||||
behavior404: .fail)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> GroupInviteLinkPreview in
|
||||
guard let protoData = response.responseData else {
|
||||
guard let protoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
let groupInviteLinkPreview = try GroupsV2Protos.parseGroupInviteLinkPreview(protoData, groupV2Params: groupV2Params)
|
||||
@ -1691,7 +1692,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior403: .expiredGroupInviteLink,
|
||||
behavior404: .fail)
|
||||
}.then(on: .global()) { (response: OWSHTTPResponse) -> Promise<TSGroupThread> in
|
||||
guard let changeActionsProtoData = response.responseData else {
|
||||
guard let changeActionsProtoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
// The PATCH request that adds us to the group (as a full or requesting member)
|
||||
@ -2165,7 +2166,7 @@ public class GroupsV2Impl: NSObject, GroupsV2Swift {
|
||||
behavior403: .fetchGroupUpdates,
|
||||
behavior404: .fail)
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> GroupsProtoGroupExternalCredential in
|
||||
guard let groupProtoData = response.responseData else {
|
||||
guard let groupProtoData = response.responseBodyData else {
|
||||
throw OWSAssertionError("Invalid responseObject.")
|
||||
}
|
||||
return try GroupsProtoGroupExternalCredential(serializedData: groupProtoData)
|
||||
|
||||
@ -413,22 +413,19 @@ public class OWSLinkPreviewManager: NSObject, Dependencies {
|
||||
self.buildOWSURLSession().dataTaskPromise(url.absoluteString, method: .get)
|
||||
.catchCancellation(andThrow: LinkPreviewError.invalidPreview)
|
||||
|
||||
}.map(on: Self.workQueue) { (httpResponse: OWSHTTPResponse) -> (URL, String) in
|
||||
let task = httpResponse.task
|
||||
guard let response = task.response as? HTTPURLResponse,
|
||||
let respondingUrl = response.url,
|
||||
response.statusCode >= 200 && response.statusCode < 300 else {
|
||||
Logger.warn("Invalid response: \(type(of: task.response)).")
|
||||
}.map(on: Self.workQueue) { (response: OWSHTTPResponse) -> (URL, String) in
|
||||
let statusCode = response.responseStatusCode
|
||||
guard statusCode >= 200 && statusCode < 300 else {
|
||||
Logger.warn("Invalid response: \(statusCode).")
|
||||
throw LinkPreviewError.fetchFailure
|
||||
}
|
||||
guard let data = httpResponse.responseData,
|
||||
let string = String(data: data, urlResponse: response),
|
||||
guard let string = response.responseBodyString,
|
||||
string.count > 0 else {
|
||||
Logger.warn("Response object could not be parsed")
|
||||
throw LinkPreviewError.invalidPreview
|
||||
}
|
||||
|
||||
return (respondingUrl, string)
|
||||
return (response.requestUrl, string)
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,13 +436,12 @@ public class OWSLinkPreviewManager: NSObject, Dependencies {
|
||||
|
||||
}.map(on: Self.workQueue) { (httpResponse: OWSHTTPResponse) -> Data in
|
||||
try autoreleasepool {
|
||||
let task = httpResponse.task
|
||||
guard let response = task.response as? HTTPURLResponse,
|
||||
response.statusCode >= 200 && response.statusCode < 300 else {
|
||||
Logger.warn("Invalid response: \(type(of: task.response)).")
|
||||
let statusCode = httpResponse.responseStatusCode
|
||||
guard statusCode >= 200 && statusCode < 300 else {
|
||||
Logger.warn("Invalid response: \(statusCode).")
|
||||
throw LinkPreviewError.fetchFailure
|
||||
}
|
||||
guard let rawData = httpResponse.responseData,
|
||||
guard let rawData = httpResponse.responseBodyData,
|
||||
rawData.count < Self.maxFetchedContentSize else {
|
||||
Logger.warn("Response object could not be parsed")
|
||||
throw LinkPreviewError.invalidPreview
|
||||
|
||||
@ -400,10 +400,10 @@ extension MessageSender {
|
||||
recipients: recipients,
|
||||
udAccessMap: udAccessMap)
|
||||
}.map(on: senderKeyQueue) { response -> SenderKeySendResult in
|
||||
guard response.statusCode == 200 else { throw
|
||||
guard response.responseStatusCode == 200 else { throw
|
||||
OWSAssertionError("Unhandled error")
|
||||
}
|
||||
let response = try Self.decodeSuccessResponse(data: response.responseData)
|
||||
let response = try Self.decodeSuccessResponse(data: response.responseBodyData)
|
||||
let uuids404 = Set(response.uuids404)
|
||||
|
||||
let successful = try recipients.filter {
|
||||
|
||||
@ -387,11 +387,12 @@ public class OWSAttachmentUploadV2: NSObject {
|
||||
let urlSession = OWSUpload.cdnUrlSession(forCdnNumber: form.cdnNumber)
|
||||
let body = "".data(using: .utf8)
|
||||
return urlSession.dataTaskPromise(urlString, method: .post, headers: headers, body: body)
|
||||
}.map(on: Self.serialQueue) { (response: OWSHTTPResponse) in
|
||||
guard response.statusCode == 201 else {
|
||||
throw OWSAssertionError("Invalid statusCode: \(response.statusCode).")
|
||||
}.map(on: Self.serialQueue) { (response: HTTPResponse) in
|
||||
let statusCode = response.responseStatusCode
|
||||
guard statusCode == 201 else {
|
||||
throw OWSAssertionError("Invalid statusCode: \(statusCode).")
|
||||
}
|
||||
guard let locationHeader = response.allHeaderFields["Location"] as? String else {
|
||||
guard let locationHeader = response.responseHeaders["Location"] else {
|
||||
throw OWSAssertionError("Missing location header.")
|
||||
}
|
||||
guard locationHeader.lowercased().hasPrefix("http") else {
|
||||
@ -614,9 +615,9 @@ public class OWSAttachmentUploadV2: NSObject {
|
||||
|
||||
return urlSession.dataTaskPromise(urlString, method: .put, headers: headers, body: body)
|
||||
}.map(on: Self.serialQueue) { (response: OWSHTTPResponse) in
|
||||
|
||||
if response.statusCode != 308 {
|
||||
owsFailDebug("Invalid status code: \(response.statusCode).")
|
||||
let statusCode = response.responseStatusCode
|
||||
if statusCode != 308 {
|
||||
owsFailDebug("Invalid status code: \(statusCode).")
|
||||
// Return zero to restart the upload.
|
||||
return 0
|
||||
}
|
||||
@ -631,7 +632,7 @@ public class OWSAttachmentUploadV2: NSObject {
|
||||
//
|
||||
// * https://cloud.google.com/storage/docs/performing-resumable-uploads#resume-upload
|
||||
// * https://cloud.google.com/storage/docs/resumable-uploads
|
||||
guard let rangeHeader = response.allHeaderFields["Range"] as? String else {
|
||||
guard let rangeHeader = response.responseHeaders["Range"] else {
|
||||
Logger.warn("Missing Range header.")
|
||||
|
||||
throw OWSUploadError.missingRangeHeader
|
||||
|
||||
@ -158,27 +158,27 @@ public class RESTSessionManager: NSObject {
|
||||
}
|
||||
|
||||
let afSuccess = { (task: URLSessionDataTask?, responseObject: Any?) in
|
||||
var responseStatus: UInt32 = 0
|
||||
let responseHeaders = parseResponseHeaders(task: task)
|
||||
guard let httpUrlResponse = parseResponse(task: task) else {
|
||||
if DebugFlags.internalLogging,
|
||||
let response = task?.response {
|
||||
Logger.warn("Invalid response: \(response)")
|
||||
}
|
||||
owsFailDebug("Invalid response")
|
||||
failure(OWSHTTPErrorWrapper(error: .invalidResponse(requestUrl: requestUrl)))
|
||||
return
|
||||
}
|
||||
// TODO: Can we extract a response body?
|
||||
var responseData: Data?
|
||||
if let response = parseResponse(task: task) {
|
||||
responseStatus = UInt32(response.statusCode)
|
||||
if let responseObject = responseObject {
|
||||
if let data = responseObject as? Data {
|
||||
responseData = data
|
||||
} else {
|
||||
owsFailDebug("Invalid response: \(type(of: responseObject))")
|
||||
}
|
||||
if let responseObject = responseObject {
|
||||
if let data = responseObject as? Data {
|
||||
responseData = data
|
||||
} else {
|
||||
owsFailDebug("Invalid response: \(type(of: responseObject))")
|
||||
}
|
||||
} else {
|
||||
owsFailDebug("Invalid response.")
|
||||
}
|
||||
let response = OWSHTTPResponseImpl(requestUrl: requestUrl,
|
||||
status: responseStatus,
|
||||
headers: responseHeaders,
|
||||
bodyData: responseData,
|
||||
message: nil)
|
||||
let response = OWSHTTPResponseImpl.build(requestUrl: requestUrl,
|
||||
httpUrlResponse: httpUrlResponse,
|
||||
bodyData: responseData)
|
||||
success(response)
|
||||
}
|
||||
|
||||
|
||||
@ -53,19 +53,7 @@ public enum HTTPMethod {
|
||||
// MARK: -
|
||||
|
||||
// TODO: Remove in favor of HTTPResponse?
|
||||
public struct OWSHTTPResponse {
|
||||
public let task: URLSessionTask
|
||||
public let httpUrlResponse: HTTPURLResponse
|
||||
public let responseData: Data?
|
||||
|
||||
public var statusCode: Int {
|
||||
httpUrlResponse.statusCode
|
||||
}
|
||||
|
||||
public var allHeaderFields: [AnyHashable: Any] {
|
||||
httpUrlResponse.allHeaderFields
|
||||
}
|
||||
}
|
||||
public typealias OWSHTTPResponse = HTTPResponse
|
||||
|
||||
// MARK: -
|
||||
|
||||
@ -271,13 +259,13 @@ public class OWSURLSession: NSObject {
|
||||
}
|
||||
|
||||
private class func uploadOrDataTaskCompletionPromise(requestConfig: RequestConfig,
|
||||
responseData: Data?) -> Promise<OWSHTTPResponse> {
|
||||
responseData: Data?) -> Promise<HTTPResponse> {
|
||||
firstly {
|
||||
baseCompletionPromise(requestConfig: requestConfig, responseData: responseData)
|
||||
}.map(on: .global()) { (httpUrlResponse: HTTPURLResponse) -> OWSHTTPResponse in
|
||||
OWSHTTPResponse(task: requestConfig.task,
|
||||
httpUrlResponse: httpUrlResponse,
|
||||
responseData: responseData)
|
||||
}.map(on: .global()) { (httpUrlResponse: HTTPURLResponse) -> HTTPResponse in
|
||||
OWSHTTPResponseImpl.build(requestUrl: requestConfig.requestUrl,
|
||||
httpUrlResponse: httpUrlResponse,
|
||||
bodyData: responseData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -786,11 +774,12 @@ public extension OWSURLSession {
|
||||
|
||||
return firstly { () -> Promise<(URLSessionTask, Data?)> in
|
||||
taskState.promise
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<OWSHTTPResponse> in
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<HTTPResponse> in
|
||||
guard let requestConfig = requestConfig else {
|
||||
throw OWSAssertionError("Missing requestConfig.")
|
||||
}
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig, responseData: responseData)
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig,
|
||||
responseData: responseData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,11 +820,12 @@ public extension OWSURLSession {
|
||||
|
||||
return firstly { () -> Promise<(URLSessionTask, Data?)> in
|
||||
taskState.promise
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<OWSHTTPResponse> in
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<HTTPResponse> in
|
||||
guard let requestConfig = requestConfig else {
|
||||
throw OWSAssertionError("Missing requestConfig.")
|
||||
}
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig, responseData: responseData)
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig,
|
||||
responseData: responseData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,11 +876,12 @@ public extension OWSURLSession {
|
||||
|
||||
return firstly { () -> Promise<(URLSessionTask, Data?)> in
|
||||
taskState.promise
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<OWSHTTPResponse> in
|
||||
}.then(on: .global()) { (_, responseData: Data?) -> Promise<HTTPResponse> in
|
||||
guard let requestConfig = requestConfig else {
|
||||
throw OWSAssertionError("Missing requestConfig.")
|
||||
}
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig, responseData: responseData)
|
||||
return Self.uploadOrDataTaskCompletionPromise(requestConfig: requestConfig,
|
||||
responseData: responseData)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@ public protocol HTTPResponse {
|
||||
var responseHeaders: [String: String] { get }
|
||||
var responseBodyData: Data? { get }
|
||||
var responseBodyJson: Any? { get }
|
||||
var responseBodyString: String? { get }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
@ -56,6 +57,7 @@ public struct HTTPErrorServiceResponse {
|
||||
public enum OWSHTTPError: Error, IsRetryableProvider {
|
||||
case invalidAppState(requestUrl: URL)
|
||||
case invalidRequest(requestUrl: URL)
|
||||
case invalidResponse(requestUrl: URL)
|
||||
// Request failed without a response from the service.
|
||||
case networkFailure(requestUrl: URL)
|
||||
// Request failed with a response from the service.
|
||||
@ -111,6 +113,8 @@ public enum OWSHTTPError: Error, IsRetryableProvider {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest:
|
||||
return false
|
||||
case .invalidResponse:
|
||||
return true
|
||||
case .networkFailure:
|
||||
return true
|
||||
case .serviceResponse:
|
||||
@ -123,7 +127,6 @@ public enum OWSHTTPError: Error, IsRetryableProvider {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,6 +140,8 @@ extension OWSHTTPError: HTTPError {
|
||||
return requestUrl
|
||||
case .invalidRequest(let requestUrl):
|
||||
return requestUrl
|
||||
case .invalidResponse(let requestUrl):
|
||||
return requestUrl
|
||||
case .networkFailure(let requestUrl):
|
||||
return requestUrl
|
||||
case .serviceResponse(let serviceResponse):
|
||||
@ -147,7 +152,7 @@ extension OWSHTTPError: HTTPError {
|
||||
// NOTE: This function should only be called from NetworkManager.swiftHTTPStatusCodeForError.
|
||||
public var responseStatusCode: Int {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return 0
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return Int(serviceResponse.responseStatus)
|
||||
@ -156,7 +161,7 @@ extension OWSHTTPError: HTTPError {
|
||||
|
||||
public var responseHeaders: OWSHttpHeaders? {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.responseHeaders
|
||||
@ -165,7 +170,7 @@ extension OWSHTTPError: HTTPError {
|
||||
|
||||
public var responseError: Error? {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.responseError
|
||||
@ -174,7 +179,7 @@ extension OWSHTTPError: HTTPError {
|
||||
|
||||
public var responseBodyData: Data? {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.responseData
|
||||
@ -188,7 +193,7 @@ extension OWSHTTPError: HTTPError {
|
||||
}
|
||||
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.customRetryAfterDate
|
||||
@ -197,7 +202,7 @@ extension OWSHTTPError: HTTPError {
|
||||
|
||||
public var customLocalizedDescription: String? {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.customLocalizedDescription
|
||||
@ -206,7 +211,7 @@ extension OWSHTTPError: HTTPError {
|
||||
|
||||
public var customLocalizedRecoverySuggestion: String? {
|
||||
switch self {
|
||||
case .invalidAppState, .invalidRequest, .networkFailure:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse, .networkFailure:
|
||||
return nil
|
||||
case .serviceResponse(let serviceResponse):
|
||||
return serviceResponse.customLocalizedRecoverySuggestion
|
||||
@ -216,9 +221,7 @@ extension OWSHTTPError: HTTPError {
|
||||
// NOTE: This function should only be called from NetworkManager.isSwiftNetworkConnectivityError.
|
||||
public var isNetworkConnectivityError: Bool {
|
||||
switch self {
|
||||
case .invalidAppState:
|
||||
return false
|
||||
case .invalidRequest:
|
||||
case .invalidAppState, .invalidRequest, .invalidResponse:
|
||||
return false
|
||||
case .networkFailure:
|
||||
return true
|
||||
@ -319,3 +322,122 @@ public extension Error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
// TODO: Rename.
|
||||
@objc
|
||||
public class OWSHTTPResponseImpl: NSObject {
|
||||
|
||||
@objc
|
||||
public let requestUrl: URL
|
||||
|
||||
@objc
|
||||
public let status: UInt32
|
||||
|
||||
@objc
|
||||
public let headers: OWSHttpHeaders
|
||||
|
||||
@objc
|
||||
public let bodyData: Data?
|
||||
|
||||
public let stringEncoding: String.Encoding
|
||||
|
||||
private struct JSONValue {
|
||||
let json: Any?
|
||||
}
|
||||
|
||||
// This property should only be accessed with unfairLock acquired.
|
||||
//
|
||||
// TODO: Type?
|
||||
private var jsonValue: JSONValue?
|
||||
|
||||
private static let unfairLock = UnfairLock()
|
||||
|
||||
public required init(requestUrl: URL,
|
||||
status: UInt32,
|
||||
headers: OWSHttpHeaders,
|
||||
bodyData: Data?,
|
||||
stringEncoding: String.Encoding = .utf8) {
|
||||
self.requestUrl = requestUrl
|
||||
self.status = status
|
||||
self.headers = headers
|
||||
self.bodyData = bodyData
|
||||
self.stringEncoding = stringEncoding
|
||||
}
|
||||
|
||||
public static func build(requestUrl: URL,
|
||||
httpUrlResponse: HTTPURLResponse,
|
||||
bodyData: Data?) -> HTTPResponse {
|
||||
let headers = OWSHttpHeaders(response: httpUrlResponse)
|
||||
let stringEncoding: String.Encoding = httpUrlResponse.parseStringEncoding() ?? .utf8
|
||||
return OWSHTTPResponseImpl(requestUrl: requestUrl,
|
||||
status: UInt32(httpUrlResponse.statusCode),
|
||||
headers: headers,
|
||||
bodyData: bodyData,
|
||||
stringEncoding: stringEncoding)
|
||||
}
|
||||
|
||||
@objc
|
||||
public var bodyJson: Any? {
|
||||
Self.unfairLock.withLock {
|
||||
if let jsonValue = self.jsonValue {
|
||||
return jsonValue.json
|
||||
}
|
||||
let jsonValue = Self.parseJSON(data: bodyData)
|
||||
self.jsonValue = jsonValue
|
||||
return jsonValue.json
|
||||
}
|
||||
}
|
||||
|
||||
private static func parseJSON(data: Data?) -> JSONValue {
|
||||
guard let data = data else {
|
||||
return JSONValue(json: nil)
|
||||
}
|
||||
do {
|
||||
let json = try JSONSerialization.jsonObject(with: data, options: [])
|
||||
return JSONValue(json: json)
|
||||
} catch {
|
||||
owsFailDebug("Could not parse JSON: \(error).")
|
||||
return JSONValue(json: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
// TODO: Modify OWSHTTPResponse to confirm to HTTPResponse as well?
|
||||
extension OWSHTTPResponseImpl: HTTPResponse {
|
||||
@objc
|
||||
public var responseStatusCode: Int { Int(status) }
|
||||
@objc
|
||||
public var responseHeaders: [String: String] { headers.headers }
|
||||
@objc
|
||||
public var responseBodyData: Data? { bodyData }
|
||||
@objc
|
||||
public var responseBodyJson: Any? { bodyJson }
|
||||
@objc
|
||||
public var responseBodyString: String? {
|
||||
guard let data = bodyData,
|
||||
let string = String(data: data, encoding: stringEncoding) else {
|
||||
Logger.warn("Invalid body string.")
|
||||
return nil
|
||||
}
|
||||
return string
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
extension HTTPURLResponse {
|
||||
fileprivate func parseStringEncoding() -> String.Encoding? {
|
||||
guard let encodingName = textEncodingName else {
|
||||
return nil
|
||||
}
|
||||
let encoding = CFStringConvertIANACharSetNameToEncoding(encodingName as CFString)
|
||||
guard encoding != kCFStringEncodingInvalidId else {
|
||||
return nil
|
||||
}
|
||||
return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(encoding))
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,90 +90,6 @@ extension OWSWebSocket {
|
||||
|
||||
// MARK: -
|
||||
|
||||
@objc
|
||||
public class OWSHTTPResponseImpl: NSObject {
|
||||
|
||||
@objc
|
||||
public let requestUrl: URL
|
||||
|
||||
@objc
|
||||
public let status: UInt32
|
||||
|
||||
@objc
|
||||
public let headers: OWSHttpHeaders
|
||||
|
||||
@objc
|
||||
public let bodyData: Data?
|
||||
|
||||
// TODO: Remove?
|
||||
@objc
|
||||
public let message: String?
|
||||
|
||||
private struct JSONValue {
|
||||
let json: Any?
|
||||
}
|
||||
|
||||
// This property should only be accessed with unfairLock acquired.
|
||||
//
|
||||
// TODO: Type?
|
||||
private var jsonValue: JSONValue?
|
||||
|
||||
private static let unfairLock = UnfairLock()
|
||||
|
||||
public required init(requestUrl: URL,
|
||||
status: UInt32,
|
||||
headers: OWSHttpHeaders,
|
||||
bodyData: Data?,
|
||||
message: String?) {
|
||||
self.requestUrl = requestUrl
|
||||
self.status = status
|
||||
self.headers = headers
|
||||
self.bodyData = bodyData
|
||||
self.message = message
|
||||
}
|
||||
|
||||
@objc
|
||||
public var bodyJson: Any? {
|
||||
Self.unfairLock.withLock {
|
||||
if let jsonValue = self.jsonValue {
|
||||
return jsonValue.json
|
||||
}
|
||||
let jsonValue = Self.parseJSON(data: bodyData)
|
||||
self.jsonValue = jsonValue
|
||||
return jsonValue.json
|
||||
}
|
||||
}
|
||||
|
||||
private static func parseJSON(data: Data?) -> JSONValue {
|
||||
guard let data = data else {
|
||||
return JSONValue(json: nil)
|
||||
}
|
||||
do {
|
||||
let json = try JSONSerialization.jsonObject(with: data, options: [])
|
||||
return JSONValue(json: json)
|
||||
} catch {
|
||||
owsFailDebug("Could not parse JSON: \(error).")
|
||||
return JSONValue(json: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
// TODO: Modify OWSHTTPResponse to confirm to HTTPResponse as well?
|
||||
extension OWSHTTPResponseImpl: HTTPResponse {
|
||||
@objc
|
||||
public var responseStatusCode: Int { Int(status) }
|
||||
@objc
|
||||
public var responseHeaders: [String: String] { headers.headers }
|
||||
@objc
|
||||
public var responseBodyData: Data? { bodyData }
|
||||
@objc
|
||||
public var responseBodyJson: Any? { bodyJson }
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
// TODO: Make this private, rename class.
|
||||
@objc
|
||||
public class SocketMessageInfo: NSObject {
|
||||
@ -217,11 +133,13 @@ public class SocketMessageInfo: NSObject {
|
||||
headers: OWSHttpHeaders,
|
||||
bodyData: Data?,
|
||||
message: String?) {
|
||||
if let message = message?.nilIfEmpty {
|
||||
Logger.verbose("message: \(message)")
|
||||
}
|
||||
let response = OWSHTTPResponseImpl(requestUrl: requestUrl,
|
||||
status: status,
|
||||
headers: headers,
|
||||
bodyData: bodyData,
|
||||
message: message)
|
||||
bodyData: bodyData)
|
||||
didSucceed(response: response)
|
||||
}
|
||||
|
||||
|
||||
@ -412,7 +412,8 @@ public struct StorageService: Dependencies {
|
||||
}.map(on: .global()) { (response: OWSHTTPResponse) -> StorageResponse in
|
||||
let status: StorageResponse.Status
|
||||
|
||||
switch response.statusCode {
|
||||
let statusCode = response.responseStatusCode
|
||||
switch statusCode {
|
||||
case 200:
|
||||
status = .success
|
||||
case 204:
|
||||
@ -422,12 +423,12 @@ public struct StorageService: Dependencies {
|
||||
case 404:
|
||||
status = .notFound
|
||||
default:
|
||||
let error = OWSAssertionError("Unexpected statusCode: \(response.statusCode)")
|
||||
throw StorageError.networkError(statusCode: response.statusCode, underlyingError: error)
|
||||
let error = OWSAssertionError("Unexpected statusCode: \(statusCode)")
|
||||
throw StorageError.networkError(statusCode: statusCode, underlyingError: error)
|
||||
}
|
||||
|
||||
// We should always receive response data, for some responses it will be empty.
|
||||
guard let responseData = response.responseData else {
|
||||
guard let responseData = response.responseBodyData else {
|
||||
owsFailDebug("missing response data")
|
||||
throw StorageError.retryableAssertion
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user