├── LICENSE.md ├── README.md ├── SwiftRequest └── SwiftRequest.swift └── Tests ├── Info.plist └── SwiftRequestTests.swift /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Ricky Robinett 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftRequest 2 | 3 | SwiftRequest is a simple HTTP client for Swift. It was inspired by the [Node.js Request library](https://github.com/mikeal/request) and [Python Requests](http://docs.python-requests.org/en/latest/). 4 | 5 | ```swift 6 | var swiftRequest = SwiftRequest() 7 | 8 | swiftRequest.get("https://en.wikipedia.org/wiki/Brooklyn", callback: {err, response, body in 9 | if( err == nil ) { 10 | println(body) 11 | } 12 | }) 13 | ``` 14 | 15 | ## Installation 16 | 17 | ### Manual 18 | 19 | Drop the SwiftRequest folder into your Xcode project. 20 | 21 | ### CocoaPods 22 | 23 | You can install SwiftRequest using [CocoaPods](http://cocoapods.org/). 24 | 25 | Swift support is currently part of CocoaPods 0.36 beta. You can install it using the following command: 26 | ``` 27 | gem install cocoapods --pre 28 | ``` 29 | 30 | Add SwiftRequest to your Podfile: 31 | ``` 32 | source 'https://github.com/CocoaPods/Specs.git' 33 | platform :ios, '8.0' 34 | 35 | pod 'SwiftRequest', '0.0.4' 36 | ``` 37 | 38 | Install it by running: 39 | ``` 40 | pod install 41 | ``` 42 | 43 | Make sure you import SwiftRequest into any Swift files you're using it in with: 44 | ``` 45 | import SwiftRequest 46 | ``` 47 | 48 | ## Getting Started 49 | 50 | ### GET Requests 51 | 52 | #### Simple GET Request 53 | ```swift 54 | var swiftRequest = SwiftRequest() 55 | 56 | swiftRequest.get("http://news.ycombinator.com", callback: {err, response, body in 57 | if( err == nil ) { 58 | println(body) 59 | } 60 | }) 61 | ``` 62 | 63 | #### GET Request with Parameters 64 | ```swift 65 | swiftRequest.get("http://pokeapi.co/api/v1/pokemon/", params: ["limit":"5"], callback: {err, response, body in 66 | if( err == nil ) { 67 | println(body) 68 | } 69 | }) 70 | ``` 71 | 72 | #### GET Request with Authentication 73 | ```swift 74 | swiftRequest.get("https://api.github.com/user", auth: ["username" : "user", "password" : "pass"],callback: {err, response, body in 75 | if( err == nil ) { 76 | println(body) 77 | } 78 | }) 79 | 80 | ``` 81 | 82 | 83 | ### POST Requests 84 | ```swift 85 | var swiftRequest = SwiftRequest() 86 | 87 | var data = [ 88 | "Name" : "Ricky", 89 | "Favorite Band" : "Refused", 90 | "Age" : "29" 91 | ] 92 | 93 | swiftRequest.post("http://requestb.in/ukfc8euk", data: data, callback: {err, response, body in 94 | if( err == nil ) { 95 | println(body) 96 | } 97 | }) 98 | ``` 99 | 100 | ### Sample GET image 101 | ```swift 102 | var swiftRequest = SwiftRequest() 103 | 104 | swiftRequest.get("http://graphics8.nytimes.com/images/2013/02/22/nyregion/KENTILE-01/KENTILE-01-articleLarge.jpg", {err, response, body in 105 | println(body) 106 | var image = UIImage(data: body as NSData) 107 | self.imageView.image = image 108 | }) 109 | 110 | ``` 111 | -------------------------------------------------------------------------------- /SwiftRequest/SwiftRequest.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftRequest.swift 3 | // SwiftRequestTest 4 | // 5 | // Created by Ricky Robinett on 6/20/14. 6 | // Copyright (c) 2015 Ricky Robinett. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public class SwiftRequest { 12 | var session = NSURLSession.sharedSession() 13 | 14 | public init() { 15 | // we should probably be preparing something here... 16 | } 17 | 18 | // GET requests 19 | public func get(url: String, auth: [String: String] = [String: String](), params: [String: String] = [String: String](), callback: ((err: NSError?, response: NSHTTPURLResponse?, body: AnyObject?)->())? = nil) { 20 | var qs = dictToQueryString(params) 21 | request(["url" : url, "auth" : auth, "querystring": qs ], callback: callback ) 22 | } 23 | 24 | // POST requests 25 | public func post(url: String, data: [String: String] = [String: String](), auth: [String: String] = [String: String](), callback: ((err: NSError?, response: NSHTTPURLResponse?, body: AnyObject?)->())? = nil) { 26 | var qs = dictToQueryString(data) 27 | request(["url": url, "method" : "POST", "body" : qs, "auth" : auth] , callback: callback) 28 | } 29 | 30 | // Actually make the request 31 | func request(options: [String: Any], callback: ((err: NSError?, response: NSHTTPURLResponse?, body: AnyObject?)->())?) { 32 | if( options["url"] == nil ) { return } 33 | 34 | var urlString = options["url"] as! String 35 | if( options["querystring"] != nil && (options["querystring"] as! String) != "" ) { 36 | var qs = options["querystring"] as! String 37 | urlString = "\(urlString)?\(qs)" 38 | } 39 | 40 | var url = NSURL(string:urlString) 41 | var urlRequest = NSMutableURLRequest(URL: url!) 42 | 43 | if( options["method"] != nil) { 44 | urlRequest.HTTPMethod = options["method"] as! String 45 | } 46 | 47 | if( options["body"] != nil && options["body"] as! String != "" ) { 48 | var postData = (options["body"] as! String).dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true) 49 | urlRequest.HTTPBody = postData 50 | urlRequest.setValue("\(postData!.length)", forHTTPHeaderField: "Content-length") 51 | } 52 | 53 | // is there a more efficient way to do this? 54 | if( options["auth"] != nil && (options["auth"] as! [String: String]).count > 0) { 55 | var auth = options["auth"] as! [String: String] 56 | if( auth["username"] != nil && auth["password"] != nil ) { 57 | var username = auth["username"] 58 | var password = auth["password"] 59 | var authEncoded = "\(username!):\(password!)".dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.allZeros); 60 | println(authEncoded) 61 | var authValue = "Basic \(authEncoded)" 62 | urlRequest.setValue(authValue, forHTTPHeaderField: "Authorization") 63 | } 64 | } 65 | 66 | let task = session.dataTaskWithRequest(urlRequest, completionHandler: {body, response, err in 67 | var resp = response as! NSHTTPURLResponse? 68 | 69 | if( err == nil) { 70 | if(response.MIMEType == "text/html") { 71 | var bodyStr = NSString(data: body, encoding:NSUTF8StringEncoding) 72 | return callback!(err: err, response: resp, body: bodyStr) 73 | } else if(response.MIMEType == "application/json") { 74 | var localError: NSError? 75 | var json: AnyObject! = NSJSONSerialization.JSONObjectWithData(body! as NSData, options: NSJSONReadingOptions.MutableContainers, error: &localError) 76 | return callback!(err: err, response: resp, body: json); 77 | } 78 | } 79 | 80 | return callback!(err: err, response: resp, body: body) 81 | }) 82 | 83 | task.resume() 84 | } 85 | 86 | func request(url: String, callback: ((err: NSError?, response: NSHTTPURLResponse?, body: AnyObject?)->())? = nil) { 87 | request(["url" : url ], callback: callback ) 88 | } 89 | 90 | private func dictToQueryString(data: [String: String]) -> String { 91 | 92 | var qs = "" 93 | for (key, value) in data { 94 | let encodedKey = encode(key) 95 | let encodedValue = encode(value) 96 | qs += "\(encodedKey)=\(encodedValue)&" 97 | } 98 | return qs 99 | } 100 | 101 | private func encode(value: String) -> String { 102 | let queryCharacters = NSCharacterSet(charactersInString:" =\"#%/<>?@\\^`{}[]|&+").invertedSet 103 | 104 | let encodedValue:String = value.stringByAddingPercentEncodingWithAllowedCharacters(queryCharacters)! 105 | 106 | return encodedValue 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | test.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/SwiftRequestTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftRequestTests.swift 3 | // SwiftRequestTests 4 | // 5 | // Created by Ricky Robinett on 6/20/14. 6 | // Copyright (c) 2014 Ricky Robinett. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SwiftRequestTests: XCTestCase { 12 | var swiftRequest = SwiftRequest() 13 | 14 | func testGet() { 15 | var expectation = expectationWithDescription("Testing Async Get"); 16 | swiftRequest.get("http://news.ycombinator.com", callback: {err, response, body in 17 | XCTAssertNotNil(response, "Response should not be nil" ) 18 | XCTAssertNotNil(body, "Body should not be nil" ) 19 | XCTAssertNil( err, "Should not receive an error" ) 20 | 21 | expectation.fulfill() 22 | }) 23 | 24 | waitForExpectationsWithTimeout(10) { (error) in 25 | if(error != nil) { XCTFail("Test timed out") } 26 | } 27 | 28 | } 29 | 30 | func testGetWithParams() { 31 | var expectation = expectationWithDescription("Testing Async Get"); 32 | 33 | swiftRequest.get("http://pokeapi.co/api/v1/pokemon/", params: [ "limit" : "5" ], callback: {err, response, body in 34 | XCTAssertNotNil(response, "Response should not be nil" ) 35 | XCTAssertNotNil(body, "Body should not be nil" ) 36 | XCTAssertNil( err, "Should not receive an error" ) 37 | 38 | expectation.fulfill() 39 | }) 40 | 41 | 42 | waitForExpectationsWithTimeout(10) { (error) in 43 | if(error != nil) { XCTFail("Test timed out") } 44 | } 45 | } 46 | 47 | func testGet404() { 48 | var expectation = expectationWithDescription("Testing Async Get 404"); 49 | 50 | swiftRequest.get("http://httpstat.us/404", callback: {err, response, body in 51 | XCTAssert(response!.statusCode == 404, "Response code should be 404" ) 52 | 53 | expectation.fulfill() 54 | }) 55 | 56 | 57 | waitForExpectationsWithTimeout(10) { (error) in 58 | if(error != nil) { XCTFail("Test timed out") } 59 | } 60 | } 61 | 62 | func testPost() { 63 | var expectation = expectationWithDescription("Testing Async Post"); 64 | 65 | swiftRequest.post("http://httpbin.org/post", data: ["test":"test"], callback: {err, response, body in 66 | XCTAssertNotNil(response, "Response should not be nil" ) 67 | XCTAssertNotNil(body, "Body should not be nil" ) 68 | XCTAssertNil( err, "Should not receive an error" ) 69 | 70 | expectation.fulfill() 71 | }) 72 | 73 | 74 | waitForExpectationsWithTimeout(10) { (error) in 75 | if(error != nil) { XCTFail("Test timed out") } 76 | } 77 | } 78 | 79 | 80 | 81 | } 82 | --------------------------------------------------------------------------------