Created
December 15, 2014 15:04
-
-
Save typester/a6dadb5bba43b21fee2b to your computer and use it in GitHub Desktop.
This file contains 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
import Foundation | |
class HTTP { | |
class Request { | |
enum Method: String { | |
case GET = "GET" | |
case HEAD = "HEAD" | |
case POST = "POST" | |
case PUT = "PUT" | |
case DELETE = "DELETE" | |
func hasContent() -> Bool { | |
switch self { | |
case .GET, .HEAD, .DELETE: | |
return false | |
case .POST, .PUT: | |
return true | |
} | |
} | |
} | |
var method: Method | |
var url: NSURL | |
var parameters: [String: AnyObject]? | |
lazy var contentData: NSData = self.buildData() | |
lazy var requestObject: NSURLRequest = self.buildRequestObject() | |
init(method: Method, url: NSURL, parameters: [String:AnyObject]? = nil) { | |
self.method = method | |
self.url = url | |
self.parameters = parameters | |
} | |
var parametersAsQuery: String { | |
if let parameters = self.parameters { | |
func encode(key:String, rawValue:String) -> String? { | |
if let value = rawValue.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) { | |
return "\(key)=\(value)" | |
} else { | |
return nil | |
} | |
} | |
var chunks = [String]() | |
for key in parameters.keys { | |
if let key = key.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) { | |
if let value = parameters[ key ] as? String { | |
if let chunk = encode(key, value) { | |
chunks.append(chunk) | |
} | |
} else if let values = parameters[ key ] as? [String] { | |
for value in values { | |
if let chunk = encode(key, value) { | |
chunks.append(chunk) | |
} | |
} | |
} else { | |
println("unsupported parameter type: \(key)") | |
continue | |
} | |
} else { | |
println("key should be utf-8") | |
continue | |
} | |
} | |
return join("&", chunks) | |
} else { | |
return "" | |
} | |
} | |
func buildData() -> NSData { | |
return self.parametersAsQuery.dataUsingEncoding(NSUTF8StringEncoding)! | |
} | |
func buildRequestObject() -> NSMutableURLRequest { | |
if self.method.hasContent() == false { | |
var urlString = self.url.absoluteString! | |
if let query = self.url.query { | |
urlString += "&" | |
} else { | |
urlString += "?" | |
} | |
urlString += self.parametersAsQuery | |
self.url = NSURL(string: urlString)! | |
} | |
let req = NSMutableURLRequest(URL: self.url) | |
req.HTTPMethod = self.method.rawValue | |
return req | |
} | |
} | |
class Response { | |
var request: Request? | |
var responseObject: NSURLResponse? | |
var error: NSError? | |
var contentData: NSData? | |
init(data: NSData?, response: NSURLResponse?, error: NSError?) { | |
self.contentData = data | |
self.responseObject = response | |
self.error = error | |
} | |
lazy var responseString: String = { | |
return NSString(data: self.contentData!, encoding: NSUTF8StringEncoding)! | |
}() | |
lazy var responseJSON: AnyObject? = { | |
return NSJSONSerialization.JSONObjectWithData(self.contentData!, options: nil, error: &self.error) | |
}() | |
} | |
class Client { | |
var base: NSURL? | |
var session: NSURLSession | |
init(base: String? = nil) { | |
if let base = base { | |
self.base = NSURL(string: base) | |
} | |
self.session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) | |
} | |
func request(method: Request.Method, _ path: String, _ parameters: [String:AnyObject]?, callback: (Response) -> Void) -> NSURLSessionTask { | |
var task: NSURLSessionTask | |
let url = NSURL(string: path, relativeToURL: self.base)! | |
let req = Request(method: method, url: url, parameters: parameters) | |
if method.hasContent() { | |
task = self.session.uploadTaskWithRequest(req.requestObject, fromData: req.contentData) { | |
[weak self] (data, response, error) -> Void in | |
let res = Response(data: data, response: response, error: error) | |
res.request = req | |
callback(res) | |
} | |
} else { | |
task = self.session.dataTaskWithRequest(req.requestObject) { | |
[weak self] (data, response, error) in | |
let res = Response(data: data, response: response, error: error) | |
res.request = req | |
callback(res) | |
} | |
} | |
task.resume() | |
return task | |
} | |
} | |
class var DefaultClient: Client { | |
struct Singleton { | |
static var obj: Client? = nil | |
static var once: dispatch_once_t = 0 | |
} | |
dispatch_once(&Singleton.once, { | |
Singleton.obj = Client() | |
}) | |
return Singleton.obj! | |
} | |
class func request(method: Request.Method, _ path: String, _ parameters: [String:AnyObject]?, callback: (Response) -> Void) -> NSURLSessionTask { | |
return DefaultClient.request(method, path, parameters, callback: callback) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment