// See the accompanying blog post: http://chris.eidhof.nl/posts/tiny-networking-in-swift.html
public enum Method: String { // Bluntly stolen from Alamofire
case OPTIONS = "OPTIONS"
case GET = "GET"
case HEAD = "HEAD"
case POST = "POST"
case PUT = "PUT"
case PATCH = "PATCH"
case DELETE = "DELETE"
case TRACE = "TRACE"
case CONNECT = "CONNECT"
}
public struct Resource {
let path: String
let method : Method
let requestBody: NSData?
let headers : [String:String]
let parse: NSData -> A?
}
public enum Reason {
case CouldNotParseJSON
case NoData
case NoSuccessStatusCode(statusCode: Int)
case Other(NSError)
}
public func apiRequest(modifyRequest: NSMutableURLRequest -> (), baseURL: NSURL, resource: Resource, failure: (Reason, NSData?) -> (), completion: A -> ()) {
let session = NSURLSession.sharedSession()
let url = baseURL.URLByAppendingPathComponent(resource.path)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = resource.method.rawValue
request.HTTPBody = resource.requestBody
modifyRequest(request)
for (key,value) in resource.headers {
request.setValue(value, forHTTPHeaderField: key)
}
let task = session.dataTaskWithRequest(request){ (data, response, error) -> Void in
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode == 200 {
if let responseData = data {
if let result = resource.parse(responseData) {
completion(result)
} else {
failure(Reason.CouldNotParseJSON, data)
}
} else {
failure(Reason.NoData, data)
}
} else {
failure(Reason.NoSuccessStatusCode(statusCode: httpResponse.statusCode), data)
}
} else {
failure(Reason.Other(error), data)
}
}
task.resume()
}
// Here are some convenience functions for dealing with JSON APIs
public typealias JSONDictionary = [String:AnyObject]
func decodeJSON(data: NSData) -> JSONDictionary? {
return NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as? [String:AnyObject]
}
func encodeJSON(dict: JSONDictionary) -> NSData? {
return dict.count > 0 ? NSJSONSerialization.dataWithJSONObject(dict, options: NSJSONWritingOptions.allZeros, error: nil) : nil
}
public func jsonResource(path: String, method: Method, requestParameters: JSONDictionary, parse: JSONDictionary -> A?) -> Resource {
let f = { decodeJSON($0) >>= parse }
let jsonBody = encodeJSON(requestParameters)
let headers = ["Content-Type": "application/json"]
return Resource(path: path, method: method, requestBody: jsonBody, headers: headers, parse: f)
}