You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionUtilitiesKit/Networking/Request.swift

104 lines
3.0 KiB
Swift

import Foundation
// MARK: - Convenience Types
Fixed a number of issues found during internal testing Added copy for an unrecoverable startup case Added some additional logs to better debug ValueObservation query errors Increased the pageSize to 20 on iPad devices (to prevent it immediately loading a second page) Cleaned up a bunch of threading logic (try to avoid overriding subscribe/receive threads specified at subscription) Consolidated the 'sendMessage' and 'sendAttachments' functions Updated the various frameworks to use 'DAWRF with DSYM' to allow for better debugging during debug mode (at the cost of a longer build time) Updated the logic to optimistically insert messages when sending to avoid any database write delays Updated the logic to avoid sending notifications for messages which are already marked as read by the config Fixed an issue where multiple paths could incorrectly get built at the same time in some cases Fixed an issue where other job queues could be started before the blockingQueue finishes Fixed a potential bug with the snode version comparison (was just a string comparison which would fail when getting to double-digit values) Fixed a bug where you couldn't remove the last reaction on a message Fixed the broken media message zoom animations Fixed a bug where the last message read in a conversation wouldn't be correctly detected as already read Fixed a bug where the QuoteView had no line limits (resulting in the '@You' mention background highlight being incorrectly positioned in the quote preview) Fixed a bug where a large number of configSyncJobs could be scheduled (only one would run at a time but this could result in performance impacts)
1 year ago
public struct Empty: Codable {
public init() {}
}
public typealias NoBody = Empty
public typealias NoResponse = Empty
public protocol EndpointType: Hashable {
var path: String { get }
}
// MARK: - Request
public struct Request<T: Encodable, Endpoint: EndpointType> {
public let method: HTTPMethod
public let server: String
public let endpoint: Endpoint
public let queryParameters: [HTTPQueryParam: String]
public let headers: [HTTPHeader: String]
/// This is the body value sent during the request
///
/// **Warning:** The `bodyData` value should be used to when making the actual request instead of this as there
/// is custom handling for certain data types
public let body: T?
// MARK: - Initialization
public init(
method: HTTPMethod = .get,
server: String,
endpoint: Endpoint,
queryParameters: [HTTPQueryParam: String] = [:],
headers: [HTTPHeader: String] = [:],
body: T? = nil
) {
self.method = method
self.server = server
self.endpoint = endpoint
self.queryParameters = queryParameters
self.headers = headers
self.body = body
}
// MARK: - Internal Methods
private var url: URL? {
return URL(string: "\(server)\(urlPathAndParamsString)")
}
private func bodyData() throws -> Data? {
// Note: Need to differentiate between JSON, b64 string and bytes body values to ensure they are
// encoded correctly so the server knows how to handle them
switch body {
case let bodyString as String:
// The only acceptable string body is a base64 encoded one
guard let encodedData: Data = Data(base64Encoded: bodyString) else {
throw HTTPError.parsingFailed
}
return encodedData
case let bodyBytes as [UInt8]:
return Data(bodyBytes)
default:
// Having no body is fine so just return nil
guard let body: T = body else { return nil }
return try JSONEncoder().encode(body)
}
}
// MARK: - Request Generation
public var urlPathAndParamsString: String {
return [
"/\(endpoint.path)",
queryParameters
.map { key, value in "\(key)=\(value)" }
.joined(separator: "&")
]
.compactMap { $0 }
.filter { !$0.isEmpty }
.joined(separator: "?")
}
public func generateUrlRequest() throws -> URLRequest {
guard let url: URL = url else { throw HTTPError.invalidURL }
var urlRequest: URLRequest = URLRequest(url: url)
urlRequest.httpMethod = method.rawValue
urlRequest.allHTTPHeaderFields = headers.toHTTPHeaders()
urlRequest.httpBody = try bodyData()
return urlRequest
}
}
extension Request: Equatable where T: Equatable {}