Skip to content

Instantly share code, notes, and snippets.

@typester
Created December 15, 2014 15:04
Show Gist options
  • Save typester/a6dadb5bba43b21fee2b to your computer and use it in GitHub Desktop.
Save typester/a6dadb5bba43b21fee2b to your computer and use it in GitHub Desktop.
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