mirror of https://github.com/oxen-io/session-ios
				
				
				
			Move HTTP utilities into their own file
							parent
							
								
									625a3b151b
								
							
						
					
					
						commit
						651aa7039d
					
				@ -0,0 +1,87 @@
 | 
			
		||||
import PromiseKit
 | 
			
		||||
 | 
			
		||||
internal enum HTTP {
 | 
			
		||||
    private static let urlSession = URLSession(configuration: .ephemeral, delegate: urlSessionDelegate, delegateQueue: nil)
 | 
			
		||||
    private static let urlSessionDelegate = URLSessionDelegateImplementation()
 | 
			
		||||
 | 
			
		||||
    // MARK: Settings
 | 
			
		||||
    private static let timeout: TimeInterval = 20
 | 
			
		||||
 | 
			
		||||
    // MARK: URL Session Delegate Implementation
 | 
			
		||||
    private final class URLSessionDelegateImplementation : NSObject, URLSessionDelegate {
 | 
			
		||||
 | 
			
		||||
        func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
 | 
			
		||||
            // Snode to snode communication uses self-signed certificates but clients can safely ignore this
 | 
			
		||||
            completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // MARK: Verb
 | 
			
		||||
    internal enum Verb : String {
 | 
			
		||||
        case get = "GET"
 | 
			
		||||
        case put = "PUT"
 | 
			
		||||
        case post = "POST"
 | 
			
		||||
        case delete = "DELETE"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // MARK: Error
 | 
			
		||||
    internal enum Error : LocalizedError {
 | 
			
		||||
        case generic
 | 
			
		||||
        case httpRequestFailed(statusCode: UInt, json: JSON?)
 | 
			
		||||
        case invalidJSON
 | 
			
		||||
 | 
			
		||||
        var errorDescription: String? {
 | 
			
		||||
            switch self {
 | 
			
		||||
            case .generic: return "An error occurred."
 | 
			
		||||
            case .httpRequestFailed(let statusCode, _): return "HTTP request failed with status code: \(statusCode)."
 | 
			
		||||
            case .invalidJSON: return "Invalid JSON."
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal static func execute(_ verb: Verb, _ url: String, parameters: JSON? = nil, timeout: TimeInterval = HTTP.timeout) -> Promise<JSON> {
 | 
			
		||||
        return Promise<JSON> { seal in
 | 
			
		||||
            let url = URL(string: url)!
 | 
			
		||||
            var request = URLRequest(url: url)
 | 
			
		||||
            request.httpMethod = verb.rawValue
 | 
			
		||||
            if let parameters = parameters {
 | 
			
		||||
                do {
 | 
			
		||||
                    guard JSONSerialization.isValidJSONObject(parameters) else { return seal.reject(Error.invalidJSON) }
 | 
			
		||||
                    request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
 | 
			
		||||
                } catch (let error) {
 | 
			
		||||
                    return seal.reject(error)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            request.timeoutInterval = timeout
 | 
			
		||||
            let task = urlSession.dataTask(with: request) { data, response, error in
 | 
			
		||||
                guard let data = data, let response = response as? HTTPURLResponse else {
 | 
			
		||||
                    print("[Loki] \(verb.rawValue) request to \(url) failed.")
 | 
			
		||||
                    return seal.reject(Error.generic)
 | 
			
		||||
                }
 | 
			
		||||
                if let error = error {
 | 
			
		||||
                    print("[Loki] \(verb.rawValue) request to \(url) failed due to error: \(error).")
 | 
			
		||||
                    return seal.reject(error)
 | 
			
		||||
                }
 | 
			
		||||
                let statusCode = UInt(response.statusCode)
 | 
			
		||||
                var json: JSON? = nil
 | 
			
		||||
                if let j = try? JSONSerialization.jsonObject(with: data, options: []) as? JSON {
 | 
			
		||||
                    json = j
 | 
			
		||||
                } else if let result = String(data: data, encoding: .utf8) {
 | 
			
		||||
                    json = [ "result" : result ]
 | 
			
		||||
                }
 | 
			
		||||
                guard 200...299 ~= statusCode else {
 | 
			
		||||
                    let jsonDescription = json?.prettifiedDescription ?? "no debugging info provided"
 | 
			
		||||
                    print("[Loki] \(verb.rawValue) request to \(url) failed with status code: \(statusCode) (\(jsonDescription)).")
 | 
			
		||||
                    return seal.reject(Error.httpRequestFailed(statusCode: statusCode, json: json))
 | 
			
		||||
                }
 | 
			
		||||
                if let json = json {
 | 
			
		||||
                    seal.fulfill(json)
 | 
			
		||||
                } else {
 | 
			
		||||
                    print("[Loki] Couldn't parse JSON returned by \(verb.rawValue) request to \(url).")
 | 
			
		||||
                    return seal.reject(Error.invalidJSON)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            task.resume()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue