Created
February 26, 2018 15:19
-
-
Save arashkashi/a80a7b4e605ddea23ae1d51ac91e9cd7 to your computer and use it in GitHub Desktop.
Minimal Network Layer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Network.swift | |
// Kirina | |
// | |
// Created by Arash Kashi on 2017-12-11. | |
// Copyright © 2017 Arash Kashi. All rights reserved. | |
// | |
import Foundation | |
import UIKit | |
/// Responsible for network communication with server. Network class uses routing information to compose the service request. | |
class Network { | |
enum NetworkError: Error { | |
case parsing(String) | |
case network | |
} | |
enum Reponse<T> { | |
case success(T) | |
case fail(NetworkError) | |
} | |
private static var timeout: TimeInterval = 5000 | |
/// url session used for communication. it has a timeout interval of 10 seconds, and allows for the cookies to be set. | |
/// For security reasons session is configured with ephemeral as it persists NO information of the session including cookies etc. | |
static var session: URLSession = { | |
let config = URLSessionConfiguration.ephemeral | |
config.timeoutIntervalForRequest = Network.timeout | |
config.httpShouldSetCookies = true | |
return URLSession(configuration: config) | |
}() | |
/// Sends the request to the server. In debug mode it logs the status of communication data | |
/// into the console. Logs are disabled in production due to security purposes. | |
/// | |
/// - Parameters: | |
/// - route: enum type variable which includes information of request such as http type, body of request, and headers. | |
/// - completion: call back in the case of finishing the network communication. The return value of completion is optional. | |
/// the details of the failed operation is not included in the completion parameter. | |
static func sendRequest(route: Routing, | |
completion: @escaping (Network.Reponse<Data>) -> Void) { | |
let url = URLComponents(string: route.baseURL.absoluteString)! | |
var req = URLRequest(url: url.url!, | |
cachePolicy: .reloadIgnoringLocalCacheData, | |
timeoutInterval: Network.timeout) | |
req.allHTTPHeaderFields = route.headers | |
req.httpMethod = route.httpMethod | |
req.httpBody = route.bodyData | |
#if DEBUG | |
print("Network Request-----------------------------------------------------------------") | |
print(req.url?.absoluteString ?? "unknown url") | |
if let validBody = route.bodyData { | |
print((String(data: validBody, encoding: .utf8) ?? "unknown body")) | |
} | |
print("--------------------------------------------------------------------------------") | |
#endif | |
Network.session.dataTask(with: req, completionHandler: { (data, urlRes, error) in | |
guard error == nil else { | |
NSLog(error!.localizedDescription) | |
DispatchQueue.main.async { completion(.fail(.network)) }; return | |
} | |
guard let valid = urlRes as? HTTPURLResponse else { completion(.fail(.network)); return } | |
#if DEBUG | |
print("Status Code-----------------------------------------------------------------") | |
print(valid.statusCode) | |
print("--------------------------------------------------------------------------------") | |
#endif | |
guard valid.statusCode == 200 else { completion(.fail(.network)); return } | |
guard let validData = data else { | |
DispatchQueue.main.async { completion(.fail(.network)) }; return | |
} | |
do { | |
#if DEBUG | |
let jsonObject = try JSONSerialization.jsonObject(with: validData) | |
let prettyData = try JSONSerialization.data(withJSONObject: jsonObject, | |
options: .prettyPrinted) | |
print(String(data: prettyData, encoding: .utf8) ?? "unknown") | |
print(String(data: validData, encoding: .utf8) ?? "unknown") | |
#endif | |
completion(.success(validData)) | |
} catch { | |
completion(.fail(.parsing(error.localizedDescription))) | |
} | |
}).resume() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment