Skip to content

Instantly share code, notes, and snippets.

@arashkashi
Created February 26, 2018 15:19
Show Gist options
  • Save arashkashi/a80a7b4e605ddea23ae1d51ac91e9cd7 to your computer and use it in GitHub Desktop.
Save arashkashi/a80a7b4e605ddea23ae1d51ac91e9cd7 to your computer and use it in GitHub Desktop.
Minimal Network Layer
//
// 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