{"id":1650,"url":"https://github.com/logansease/QwikHttp","last_synced_at":"2025-08-02T04:32:08.593Z","repository":{"id":12155308,"uuid":"69925530","full_name":"logansease/QwikHttp","owner":"logansease","description":"a robust, yet lightweight and simple to use HTTP networking library for iOS, tvOS and watchOS","archived":false,"fork":false,"pushed_at":"2024-06-26T16:56:05.000Z","size":595,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-21T13:34:33.646Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/logansease.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-10-04T01:33:53.000Z","updated_at":"2024-06-26T16:55:46.000Z","dependencies_parsed_at":"2025-04-14T19:19:01.819Z","dependency_job_id":"a478473f-1d68-4db8-b329-5ad23f622873","html_url":"https://github.com/logansease/QwikHttp","commit_stats":null,"previous_names":[],"tags_count":90,"template":false,"template_full_name":null,"purl":"pkg:github/logansease/QwikHttp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/logansease%2FQwikHttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/logansease%2FQwikHttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/logansease%2FQwikHttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/logansease%2FQwikHttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/logansease","download_url":"https://codeload.github.com/logansease/QwikHttp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/logansease%2FQwikHttp/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268334615,"owners_count":24233793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:15:52.318Z","updated_at":"2025-08-02T04:32:08.254Z","avatar_url":"https://github.com/logansease.png","language":"Swift","funding_links":[],"categories":["Networking"],"sub_categories":["Video","Other free courses"],"readme":"# QwikHttp\n\nQwikHttp is a robust, yet lightweight and simple to use HTTP networking library. It allows you to customize every aspect of your http requests within a single line of code, using a Builder style syntax to keep your code super clean.\n\nWhat separates QwikHttp from other Networking Libraries is its: \n- light weight implementation \n- simple usage syntax\n- use of generics and QwikJson for robust serialization and deserialization\n- broad multi-platform support\n- simple, yet robust loading indicator support\n- response interceptors to provide a method to handle unauthorized responses and token refreshing with ease.\n- Swift concurrency support\n\nQwikHttp is written in Swift 5 and works great with Swift. It even works great (without generics) with objective-c. It utilizes the most recent ios networking API, NSURLSession. QwikHttp is compatible with iOS 9+, tvOS, WatchOS 2 and OSX 10.9+. \nFor a Swift 2 and objective-c compatible version, please see version 1.6.11\n\n## Usage\n\nHere are some example of how easy it is to use QwikHttp.\n\n### A simple request\n\n```swift\nQwikHttp(\"https://api.com\", httpMethod: .get).send()\n```\n\n### Swift Concurrency Support\n```\n    Task {\n        let request = QwikHttp(\"https://resttest2016.herokuapp.com/restaurants\", httpMethod: .get).addUrlParams([\"format\" : \"json\"])\n        let response = await request.getArrayResponse(Restaurant.self)\n        switch response {\n        case .success(let result):\n            UIAlertController.showAlert(withTitle: \"Success\", andMessage: String(format: \"We Found %li with async, response code: %li\",result.count, request.responseStatusCode), from: self)\n        case .failure(let error):\n            UIAlertController.showAlert(withTitle: \"Failure\", andMessage: String(format: \"Load error \\(error)\"), from: self)\n        }\n    }\n```\n\n### Parameters and Headers\n\nYou can set json, url or form encoded parameters\n```swift\nlet params = [\"awesome\" : \"true\"]\n\n//url parameters\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .addUrlParameters(params)\n    .send()\n\n//form parameters\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .addParameters(params)\n    .setParameterType(.urlEncoded)\n    .send()\n\n//json parameters\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .addParameters(params)\n    .setParameterType(.json)\n    .send()\n```\n\nYou can set the body directly and add your own headers\n```swift\nlet data =  UIImagePNGRepresentation(someImage);\nlet headers = [\"Content-Type\": \"image/png\"]\nQwikHttp(\"https://api.com\", httpMethod: .post)\n    .setBody(data)\n    .addHeaders(headers)\n    .send()\n```\n\n### Generic\n\nNote QwikHttp uses Generic completion handlers. Tell it what type you expect back in the response and it will handle your conversion.\n\nThe following Generic Types are supported by default. New types can be added by implementing the QwikDataConversion Protocol, which converts from NSData\n- NSDictionary: Parsed from a JSON response\n- NSString\n- Bool: True if the request was successful\n- NSNumber\n- NSData\n- Arrays: These are supported via using the type of the array contents and calling the array completion handler as described below. Types supporting Arrays by default are Strings, Dictionaries and QwikJson Objects\n- Codable: Swifts new JSON encoding protocol, Codable is supported with QwikHttp. To use the codable type, your objects should implement the QwikHttp.QwikCodable protocol, which is an extension of Codable.\n- For complex types, extend QwikJson to easily convert between dictionaries and complex objects and arrays ( see more below)\n\n\n#### Typed Result Handlers\n\nDepending on your needs, you may wish to call the objectHandler if you are expecting a single object, or the array handler. If you do not care, you can even use a simple (optional) boolean typed result handler.\n\n#### Get Object\n```swift\nQwikHttp(url: \"https://api.com\", httpMethod: .get)\n    .getResponse(NSDictionary.self,  { (result, error, request) -\u003e Void in\n\n    if let resultDictionary = result\n    {\n        //have fun with your JSON Parsed into a dictionary!\n    }\n    else if let resultError = error\n    {\n        //handle that error ASAP\n    }\n)}\n```\n#### Get Array\n```swift\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .getResponseArray(NSDictionary.self, { (result, error, request) -\u003e Void in\n\n    if let resultArray = result\n    {\n        //have fun with your JSON Parsed into an array of dictionaries\n    }\n    else if let resultError = error\n    {\n        //handle that error ASAP\n    }\n)}\n```\n#### Pass / Fail Boolean Response Handler\n\nYou may also use a simple Yes/No success response handler.\n```swift\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .send { (success) -\u003e Void in\n\n    //if success do x\n}\n```\n\n#### More Detailed Response\n\nResponse objects are saved in the request object and available to use for more low level handling.\n```swift\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .getResponse(NSString.self,  { (result, error, request) -\u003e Void in\n    if let responseCode = request.response.responseCode\n    {\n        //check for 403 responses or whatever\n    }\n    if let responseString = request.responseString\n    {\n        //handle the response as a string directly\n    }\n    if let responseData = request.responseData\n    {\n        //handle the response as nsdata directly\n    }\n)}\n```\n\n#### Threading\nYou can tell QwikHttp if you'd prefer your response handlers to occur on the main thread or the background thread.\nBy default, all response handlers will be called on the Main Thread, however you can easily change this default or set it on a per request level.\n\n```swift\nQwikHttpConfig.setDefaultResponseThread(.Background)\n\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .setResponseThread(.Main)\n    .send()\n```\n\n### QwikJson\nQwikJson, our Json serialization library, is now directly integrated with QwikHttp. This means that there is built in support for a range of complex model objects.\n\nFor full documentation on QwikJson, see my repo at https://github.com/logansease/QwikJson\n\nEssentially, just subclass QwikJson in a complex model object and you can serialize and deserialize those model objects automatically with QwikHttp.\n\n```swift\n//declare your complex class with whatever properties\npublic Class MyModel : QwikJson\n{\n    @objc var myProperty = \"sweet\"\n}\n```\n* NOTE: When using Swift 4 all properties must be prefaced with @objc for them to be serialized / deserialized.\n\nNow you can pass and return QwikJson Objects to and from your RESTful API with ease!\n```swift\nlet model = MyModel()\n\nQwikHttp(\"https://api.com\", httpMethod: .post)\n    .setObject(model)\n    .getResponse(MyModel.self,  { (result, error, request) -\u003e Void in\n    if let result as? Model\n    {\n        //you got a model back, with no parsing code!\n    }\n})\n```\n\nIt even works with arrays\n```swift\nlet model = MyModel()\nlet models = [model]\n\nQwikHttp(\"https://api.com\", httpMethod: .post)\n    .setObjects(models)\n    .getArrayResponse(MyModel.self, { (results, error, request) -\u003e Void in\n    if let modelArray = results as? [Model]\n    {\n        //you got an array of models back, with no parsing code!\n    }\n})\n```\n\n### Loading Indicators\n\nBy using the QwikHttpLoadingIndicatorDelegate protocol, you can provide an interface for QwikHttp to show and hide loading indicators during your http requests, allowing you to use any indicator you'd like, but allowing you to set it up and let QwikHttp handle it.\n\nOnce the default indicator delegate is set to QwikHttpConfig, Simply call the setLoadingTitle Method on your QwikHttp object and an indicator will automatically show when your request is running and hide when it completes\n\n```swift\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .setLoadingTitle(\"Loading\")\n    .send()\n```\n\nYou can set the default title for the loading indicator, passing a nil title will keep it hidden (this is the default behavior), passing a string, even an empty one will make your indicator show and hide automatically by default\n```swift\n//hide the indicator by default\nQwikHttpConfig.setDefaultLoadingTitle(nil)\n\n//show the indicator with no title by default\nQwikHttpConfig.setDefaultLoadingTitle(\"\")\n```\n\n#### QwikHttpLoadingIndicator Delegate\nQwikHttp will allow you to easily use your own loading indicator class by setting the QwikHttpLoadingIndicatorDelegate on QwikHttpConfig. You can do this to use cool indicators like MBProgressHUD or SwiftSpinner but let QwikHttp handle showing and hiding them so you don't have to.\n\nThe example below shows using a singleton helper class to handle your indicators, but this could be done in your app delegate, data service class, or within a view controller.\n```swift\nimport SwiftSpinner\npublic class QwikHelper :  QwikHttpLoadingIndicatorDelegate\n{\n    public class func shared() -\u003e QwikHelper {\n    struct Singleton {\n        static let instance = QwikHelper()\n    }\n\n    QwikHttpConfig.loadingIndicatorDelegate = Singleton.instance\n        return Singleton.instance\n    }\n\n    @objc public func showIndicator(title: String!)\n    {\n        SwiftSpinner.show(title)\n    }\n\n    @objc public func hideIndicator()   \n    {\n        SwiftSpinner.hide()\n    }\n}\n```\n\n### Standard Headers\nConfigure the requests to all send a set of stanard headers without the need to explicitly send them on every request\n```\nQwikHttpConfig.standardHeaders = [\"api_key\" : \"123123\" ]\n```\n\nEasily remove the standard headers on particlar requests\n```\nQwikHttp(\"http://test.com\", httpMethod: .get)\n    .setAvoidStandardHeaders(true).run()\n```\n\n### Response \u0026 Request Interceptors\nQwikHttp allows you to set a response interceptor that can selectively be called before each response is returned. Using this interceptor, you can do cool things like alter your responses in some way, or even cleanly handle unauthorized responses, allowing you to refresh an oAuth token or show the login screen under certain conditions.\n\nYou may also use a Request Interceptor to intercept requests before they are even sent. This could allow you to detect that a token is expired or that an action is not authorized before even sending your request.\n\nNote that interceptors can be disabled on a per request basis\n```swift\npublic class QwikHelper : QwikHttpResponseInterceptor, QwikHttpRequestInterceptor\n{\n    public class func shared() -\u003e QwikHelper {\n    struct Singleton {\n        static let instance = QwikHelper()\n    }\n    QwikHttpConfig.responseInterceptor = Singleton.instance\n        return Singleton.instance\n    }\n\n    @objc public func shouldInterceptResponse(response: NSURLResponse!) -\u003e Bool\n    {\n        //TODO check for an unautorized response and return true if so\n        return false\n    }\n\n    @objc public func interceptResponse(request : QwikHttp!, handler: (NSData?, NSURLResponse?, NSError?) -\u003e Void)\n    {\n        //TODO check to see if response means that the token must be refreshed\n        //if the token needs refreshing, refresh it- then save the new token to your auth service\n        //now update the auth header in the QwikHttp request and reset and run it again.\n        //call the handler with the results of the new request.\n    }\n\n    public func shouldInterceptRequest(request: QwikHttp!) -\u003e Bool\n    {\n        //check for an expired token date on your current token\n        return true\n    }\n\n    public func interceptRequest(request : QwikHttp!,  handler: (NSData?, NSURLResponse?, NSError?) -\u003e Void)\n    {\n        //TODO refresh your token, restart the request\n        //update the auth headers with the new token\n        request.getResponse(NSData.self) { (data, error, request) -\u003e Void! in\n        handler(data,request.response,error)\n    }\n}\n```\n\n### Logging\nYou can easily view request level information from your http requests with the request.printDebugInfo() command.\nThis will result in something like this in your debugger\n```\n----- QwikHttp Request -----\nPOST to https://www.server.com/api/oauth/token/\nHEADERS:\nContent-Type: application/x-www-form-urlencoded\nBODY:\ngrant_type=password\u0026password=Password\nRESPONSE: 200\n{\"access_token\": \"AXr4YoEAqwvrFz3BeAJZPKWf4z7Zkz\"}\n```\nYou may also set a default logging level on QwikHttpConfig so that debug information is printed by default. The levels are:\n- error (Default) which will print a debug statement any time there is an error\n- request: which will print a debug statement for every request\n- debug: which will do the above plus print debug, low level info during the request process\n- none: turn off logging\n\nThis can be set at a global level via QwikHttpConfig, and override at the request level with QwikHttp.setLoggingLevel()\n\n### Retain it and re run it\nsince QwikHttp is an object, you can hold on to it, pass it around and run it again!\n\n```swift\n\nvar qwikHttp : QwikHttp\nfunc setup()\n{\n    let self.qwikHttp = QwikHttp(\"https://api.com\", httpMethod: .get)\n    run(self.qwikHttp)\n\n    //run it again after some delay\n    NSThread.sleep(1000)\n    self.qwikHttp.reset()\n    run(self.qwikHttp)\n}\n\nfunc run(qwikHttp: QwikHttp)\n{\n    qwikHttp.send()\n}\n\n```\nThis also means that if you don't want to use the inline, builder style syntax, you don't have to!\n```swift\nlet self.qwikHttp = QwikHttp(\"https://api.com\", httpMethod: .get)\nself.qwikHttp.addParams([:])\nself.qwikHttp.addHeaders([:])\nself.qwikHttp.run()\n```\n\n## More Optional Configuration\n\n### Set time out and cache Policy per request\n\n```swift\nqwikHttp.setTimeOut(200)\nqwikHttp.setCachePolicy(NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData)\nqwikHttp.setResponseThread(.Background)\n```\n\n\n### Set Default Behaviors\n\nSet for all your requests unless overwritten\n```swift\nQwikHttpConfig.defaultTimeOut = 300\nQwikHttpConfig.defaultParameterType = .FormEncoded\nQwikHttpConfig.defaultLoadingTitle = \"Loading\"\nQwikHttpConfig.defaultCachePolicy = .ReloadIgnoringLocalCacheData\nQwikHttpConfig.setDefaultResponseThread(.Background)\n```\n\n### Custom Url Session\n\nCustomize the URL Session to provide your own URL Session Delegate. This is useful to handle the delegate's URLSession:didReceiveChallenge method. If not specified UrlSession.shared will be used.\n\n```\nQwikHttpConfig.urlSession = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)\n\npublic func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -\u003e Void) {\n\n    completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))\n}\n```\n\nYou can set per request by creating a new request sender with your custom URL session. \n```\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .setRequestSender(UrlSessionRequestSender(urlSession: URLSession.shared))\n    .send()\n```\n\n### Custom Request Senders\n\nBy default, requests are sent with the UrlSessionRequestSender and the shared URL Session, but you may create new classes that \nimplement the QwikHttpRequestSender protocol to send request with another mechanism like UrlConnection, or to mock the calls.\n\n```\n// this is our protocol definition\n@objc public protocol QwikHttpRequestSender {\n    @objc func sendRequest(_ request: URLRequest, handler: @escaping (Data?, URLResponse?, Error?) -\u003e Void)\n}\n\n// create your new request sender class\nclass MockRequestSender: QwikHttpRequestSender {\n    public func sendRequest(_ request: URLRequest, handler: @escaping (Data?, URLResponse?, Error?) -\u003e Void)\n    {\n        let mockResult = \"Mock. Yeah!\".data(using: .utf8)\n        handler(mockResult, nil, nil)\n    }\n}\n\n// pass your request sender during request creation\nQwikHttp(\"https://api.com\", httpMethod: .get)\n    .setRequestSender(MockRequestSender())\n    .send()\n\n```\n\n## Objective C\n\nQwikHttp is compatible with objective-c by importing its objective-c class file. The objective c version of QwikHttp supports most of what the Swift version supports, except for Generics.\nInstead of using generic type handlers, you may use the boolean handler or a string, data, dictionary or array (of dictionaries) handler and then utilize QwikJson to deserialize your objects if necessary.\n\n```objective-c\n#import \"QwikHttp-Swift.h\"\n\n@implementation ObjcViewController\n\n-(IBAction)sendRequest:(id)sender\n{\n    [[[[QwikHttp alloc]init:@\"https://resttest2016.herokuapp.com/restaurants\" \n        httpMethod:HttpRequestMethodGet] \n        addUrlParams:@{@\"format\" : @\"json\"}]\n        getArrayResponse:^(NSArray * results, NSError * error, QwikHttp * request) {\n\n        if(results)\n        {\n            NSArray * restaurants = [Restaurant arrayForJsonArray:data ofClass:[Restaurant class]];\n            [UIAlertController showAlertWithTitle:@\"Success\" andMessage:[NSString stringWithFormat:@\"Got %li\",(long)restaurants.count] from:self];\n        }\n    }];\n}\n```\n\n\n## Installation\n\n### Pods\nQwikHttp is available through [CocoaPods](https://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod \"QwikHttp\"\n```\n\n## Swift compatibility errors\n\nIf you experience this build error and you have already run Edit -\u003e Convert -\u003e to current Swift syntax, try adding the following to your podfile\n\"Use Legacy Swift Language Version” (SWIFT_VERSION) is required to be configured correctly...\"\n- Select the Pods project from your explorer in XCode\n- Select the QwikHttp target\n- Under project settings, find the LEGACY SWIFT VERSION, set it to No. Even if it is already set, set it again.\n\n\n## Further Notes\n\nAlso, checkout the SeaseAssist pod for a ton of great helpers to make writing your iOS code even simpler!\nhttps://github.com/logansease/SeaseAssist\n\n## Author\n\nLogan Sease, lsease@gmail.com\n\nIf you use and enjoy QwikHttp, I would LOVE to hear from you. I am very excited about this project and would love some feedback.\n\n## License\n\nQwikHttp is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogansease%2FQwikHttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flogansease%2FQwikHttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flogansease%2FQwikHttp/lists"}