Last active
September 21, 2015 19:43
-
-
Save robertBojor/40b4b5e3fe93a11bda24 to your computer and use it in GitHub Desktop.
Revisions
-
robertBojor revised this gist
Sep 21, 2015 . 1 changed file with 1 addition and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -18,6 +18,7 @@ public class ApiManager: NSObject { let apiBaseURL = "https://api.yourdomain.com/" let apiVersionStub = "v1/" /* Endpoint format: METHOD~URL_STUB with possible parameters expressed as ? */ let kEndpointAuth = "POST~auth" let kEndpointUserAdd = "POST~users" let kEndpointUserGetDetails = "GET~users/?" -
robertBojor revised this gist
Sep 21, 2015 . 1 changed file with 0 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,6 @@ // import Foundation public class ApiManager: NSObject { -
robertBojor revised this gist
Sep 21, 2015 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,5 @@ // // APIManager.swift // // Created by Robert Bojor on 21/09/15. // Copyright (c) 2015 Robert Bojor. All rights reserved. -
robertBojor created this gist
Sep 21, 2015 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,342 @@ // // ConnectionManager.swift // BiConnect // // Created by Robert Bojor on 21/09/15. // Copyright (c) 2015 Robert Bojor. All rights reserved. // import Foundation import SystemConfiguration public class ApiManager: NSObject { let localStore = NSUserDefaults.standardUserDefaults() var errorDomain:String = "com.yourdomain.api" var authHeaderName = "X-Authorization" var authFieldInLocalStorage = "authToken" let apiBaseURL = "https://api.yourdomain.com/" let apiVersionStub = "v1/" let kEndpointAuth = "POST~auth" let kEndpointUserAdd = "POST~users" let kEndpointUserGetDetails = "GET~users/?" let kEndpointUserUpdateDetails = "POST~users/?" public enum ErrorCodes:Int { case AuthFailed = 0, AuthMissing = 1, UnknownErrorOnServer = 2, ServerISEError = 3 } public enum ErrorMessages:String { case EmptyAPIURL = "API URL cannot be empty", EmptyAPIVersion = "API version cannot be empty", CheckingForNetwork = "Checking if connected to network", NotConnected = "Not connected to the internet", ConnectedToInternet = "Connected to internet", EmptyCredentials = "Authentication credentials cannot be empty", AuthTokenNotFound = "authToken was not found", AuthTokenFound = "authToken found and saved" } public enum MimeTypes:String { case ApplicationAtomXML = "application/atom+xml", ApplicationVnd = "application/vnd.dart", ApplicationECMAScript = "application/ecmascript", ApplicationEDIX12 = "application/EDI-X12", ApplicationEDIFACT = "application/EDIFACT", ApplicationJSON = "application/json", ApplicationJavaScript = "application/javascript", ApplicationOctetStream = "application/octet-stream", ApplicationOGG = "application/ogg", ApplicationDashXML = "application/dash+xml", ApplicationPDF = "application/pdf", ApplicationPostScript = "application/postscript", ApplicationRDF = "application/rdf+xml", ApplicationRSS = "application/rss+xml", ApplicationSOAP = "application/soap+xml", ApplicationWOFF = "application/font-woff", ApplicationXHTML = "application/xhtml+xml", ApplicationXML = "application/xml", ApplicationDTD = "application/xml-dtd", ApplicationXOP = "application/xop+xml", ApplicationZIP = "application/zip", ApplicationGzip = "application/gzip", ApplicationNACL = "application/x-nacl", ApplicationPNACL = "application/x-pnacl", ApplicationSMIL = "application/smil+xml", AudioBasic = "audio/basic", AudioL24 = "audio/L24", AudioMP4 = "audio/mp4", AudioMPEG = "audio/mpeg", AudioOGG = "audio/ogg", AudioFlac = "audio/flac", AudioOpus = "audio/opus", AudioVorbis = "audio/vorbis", AudioRealAudio = "audio/vnd.rn-realaudio", AudioWAV = "audio/vnd.wave", AudioWebM = "audio/webm", ImageGIF = "image/gif", ImageJPEG = "image/jpeg", ImagePJPEG = "image/pjpeg", ImagePNG = "image/png", ImageSVG = "image/svg+xml", ImageTiff = "image/tiff", ImageDjVu = "image/vnd.djvu", MessageHTTP = "message/http", MessageIMDN = "message/imdn+xml", MessagePartial = "message/partial", MessageRFC822 = "message/rfc822", ModelIGS = "model/iges", ModelMesh = "model/mesh", ModelVRML = "model/vrml", ModelX3DISO = "model/x3d+binary", ModelX3DFastInfoSet = "model/x3d+fastinfoset", ModelX3DVRML = "model/x3d-vrml", ModelX3DXML = "model/x3d+xml", MultipartMixed = "multipart/mixed", MultipartAlternative = "multipart/alternative", MultipartRelated = "multipart/related", MultipartFormData = "multipart/form-data", MultipartSigned = "multipart/signed", MultipartEncrypted = "multipart/encrypted", TextCMD = "text/cmd", TextCSS = "text/css", TextCSV = "text/csv", TextHTML = "text/html", TextPlain = "text/plain", TextRTF = "text/rtf", TextvCard = "text/vcard", TextALanguage = "text/vnd.a", TextABCNotation = "text/vnd.abc", TextXML = "text/xml", VideoAVI = "video/avi", VideoMPEG = "video/mpeg", VideoMP4 = "video/mp4", VideoOGG = "video/ogg", VideoQuicktime = "video/quicktime", VideoWebM = "video/webm", VideoMatroska = "video/x-matroska", VideoWMV = "video/x-ms-wmv", VideoFLV = "video/x-flv" } func NSURLByAppendingQueryParameters(URL : NSURL!, queryParameters : Dictionary<String, String>) -> NSURL { let URLString : NSString = NSString(format: "%@?%@", URL.absoluteString, self.stringFromQueryParameters(queryParameters)) return NSURL(string: URLString as String)! } func stringFromQueryParameters(queryParameters : Dictionary<String, String>) -> String { var parts:[String] = [] for (name, value) in queryParameters { let part = name.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLFragmentAllowedCharacterSet())! + "=" + value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLFragmentAllowedCharacterSet())! parts.append(part) } return parts.joinWithSeparator("&") } func dataToJSONObject(data:NSData) -> NSDictionary { var jsonObject = NSDictionary() do { jsonObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary } catch { jsonObject = ["payload":NSString(data: data, encoding: NSUTF8StringEncoding) as! String] } return jsonObject } public func sendRequest(toEndpoint:String, withURLParams:Array<String>?, withAuthentication:Bool, withHeaders:Dictionary<String,String>?, withParameters:Dictionary<String,String>?, withSuccess:(responsePayload:NSDictionary!, statusCode:Int!) -> Void, withFailure:(responsePayload:NSDictionary!, statusCode:Int, andError:NSError!)->Void) -> Void { let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration() let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) let urlParts = toEndpoint.componentsSeparatedByString("~") let requestMethod = urlParts[0] var endpointURL = urlParts[1] if (withURLParams != nil && withURLParams!.count > 0) { for(_, val) in withURLParams!.enumerate() { let occurence = endpointURL.rangeOfString("?") if (occurence != nil) { endpointURL = endpointURL.stringByReplacingCharactersInRange(occurence!, withString: "\(val)") } } } endpointURL = self.apiBaseURL + self.apiVersionStub + endpointURL var URL = NSURL(string: endpointURL) if requestMethod == "GET" && withParameters != nil && withParameters!.count > 0 { URL = self.NSURLByAppendingQueryParameters(URL, queryParameters: withParameters!) } let request = NSMutableURLRequest(URL: URL!) request.HTTPMethod = requestMethod request.addValue("application/json", forHTTPHeaderField: "Accept") if requestMethod == "POST" { request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") } if (withHeaders != nil && withHeaders!.count > 0) { for(key, val) in withHeaders!.enumerate() { request.addValue("\(val)", forHTTPHeaderField: "\(key)") } } if (withAuthentication) { let authToken:String = localStore.objectForKey(self.authFieldInLocalStorage) as! String if authToken == "" { let errorCode = ErrorCodes.AuthMissing.rawValue let userInfoError = ["description":"Authentication has not been performed"] let authError = NSError(domain: errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: nil, statusCode: 0, andError: authError) } request.addValue(authToken, forHTTPHeaderField: self.authHeaderName) } if requestMethod == "POST" && withParameters != nil && withParameters!.count > 0 { let queryParameters = stringFromQueryParameters(withParameters!) request.HTTPBody = queryParameters.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true) } let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in let responseStatusCode = (response as! NSHTTPURLResponse).statusCode if (error == nil) { switch (responseStatusCode) { // Everything ok case 200: withSuccess(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode) break // Bad request, Unauthorised request, Internal Server Error case 400, 403, 500: withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode, andError: error!) break case 500: let errorCode = ErrorCodes.ServerISEError.rawValue let userInfoError = ["description":"Internal Server Error - Data attached, if any"] let serverError = NSError(domain: self.errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: 500, andError: serverError) break // None of the above default: let errorCode = ErrorCodes.UnknownErrorOnServer.rawValue let userInfoError = ["description":"Unknown Server Error - Data attached, if any"] let serverError = NSError(domain: self.errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: 0, andError: serverError) break } } else { withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode, andError: error!) } }) task.resume() } public func sendUploadRequest(toEndpoint toEndpoint:String, withURLParams:Array<String>?, withAuthentication:Bool, withHeaders:Dictionary<String,String>?, withParameters:Dictionary<String,String>?, withFilePath:String?, withFileName:String?, withFileContentType:MimeTypes?, withSuccess:(responsePayload:NSDictionary!, statusCode:Int!) -> Void, withFailure:(responsePayload:NSDictionary!, statusCode:Int, andError:NSError!)->Void) -> Void { let boundary = "__RB_HELPER_BOUNDARY__" var bodyString = "" var separator = "" var bodyData = NSMutableData() let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration() let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) let urlParts = toEndpoint.componentsSeparatedByString("~") let requestMethod = urlParts[0] var endpointURL = urlParts[1] if (withURLParams != nil && withURLParams!.count > 0) { for(_, val) in withURLParams!.enumerate() { let occurence = endpointURL.rangeOfString("?") if (occurence != nil) { endpointURL = endpointURL.stringByReplacingCharactersInRange(occurence!, withString: "\(val)") } } } endpointURL = self.apiBaseURL + self.apiVersionStub + endpointURL let URL = NSURL(string: endpointURL) let request = NSMutableURLRequest(URL: URL!) request.HTTPMethod = requestMethod if (withHeaders != nil && withHeaders!.count > 0) { for(key, val) in withHeaders!.enumerate() { request.addValue("\(val)", forHTTPHeaderField: "\(key)") } } if (withAuthentication) { let authToken:String = localStore.objectForKey(self.authFieldInLocalStorage) as! String if authToken == "" { let errorCode = ErrorCodes.AuthMissing.rawValue let userInfoError = ["description":"Authentication has not been performed"] let authError = NSError(domain: errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: nil, statusCode: 0, andError: authError) } request.addValue(authToken, forHTTPHeaderField: self.authHeaderName) } if (withParameters != nil && withParameters!.count > 0) { for(paramKey, paramVal) in withParameters!.enumerate() { bodyString = "\(separator)--\(boundary)\r\nContent-Disposition: form-data; name=\"\(paramKey)\"\r\n\r\n\(paramVal)" separator = "\r\n" bodyData.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) } } if (withFilePath != nil) { let fileData = NSData(contentsOfFile: withFilePath!) if ((fileData) != nil) { bodyString = "\(separator)--\(boundary)\r\nContent-Disposition: form-data; name=\"payload\"; filename=\"\(withFileName)\"\r\nContent-Type: \(withFileContentType!.rawValue)\r\n\r\n" separator = "\r\n" bodyData.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) bodyData.appendData(fileData!) bodyData.appendData(separator.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) } } bodyString = "--\(boundary)--\r\n" bodyData.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) request.HTTPBody = bodyData let task = session.dataTaskWithRequest(request, completionHandler: { (data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in let responseStatusCode = (response as! NSHTTPURLResponse).statusCode if (error == nil) { switch (responseStatusCode) { // Everything ok case 200: withSuccess(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode) break // Bad request, Unauthorised request, Internal Server Error case 400, 403, 500: withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode, andError: error!) break case 500: let errorCode = ErrorCodes.ServerISEError.rawValue let userInfoError = ["description":"Internal Server Error - Data attached, if any"] let serverError = NSError(domain: self.errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: 500, andError: serverError) break // None of the above default: let errorCode = ErrorCodes.UnknownErrorOnServer.rawValue let userInfoError = ["description":"Unknown Server Error - Data attached, if any"] let serverError = NSError(domain: self.errorDomain, code: errorCode, userInfo: userInfoError) withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: 0, andError: serverError) break } } else { withFailure(responsePayload: self.dataToJSONObject(data!), statusCode: responseStatusCode, andError: error!) } }) task.resume() } }