swift http request can't get non-200 response - ios

I am using below swift code to make a http request. If the server response 200 OK response, swift can work properly. However, the completionHandler callback never get called until timeout when the server response other than 200 status. Is there any other setting on swift to prevent receiving other status response?
let urlStr = "http://xxxxx"
let url = NSURL(string: urlStr)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "post"
let task = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {(data, response, error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else {
// no response code
print("response")
return
}
print("get response from register service \(data) \(error)")
})
task.resume()
If that happens, I get timeout error below:
get login response nil error:Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSErrorFailingURLStringKey=http://XXXXX, NSErrorFailingURLKey=http://localhost:8080/nurse/login, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2103, NSLocalizedDescription=The request timed out.})
Also I tested with curl command and I was able to get the response as below. So the server side works fine for me. I believe the problem is on the client side.
$ curl -i -X POST -d 'mobile=1234' http://localhost:8080/nurse/login
HTTP/1.1 10029
Server: Apache-Coyote/1.1
X-Application-Context: application
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: access_token
Content-Type: text/plain;charset=UTF-8
Content-Length: 18
Date: Thu, 24 Mar 2016 02:39:09 GMT

This seems like a server side problem. The code below works (in Playground):
Try using this url and see if this is happening for you.
Also, I would use a simple tool like curl to test manually your server side before debugging Swift code:
curl -i -X POST -d 'name=yoyo' http://putsreq.com/vccZnwiNpP23RF7nwOPE
EDIT
Here is a function that does what you want. I hardcoded your URL and things are working now.
func postSomeStuff(data: String, completion: (data: NSData?, error: NSError?)->Void) {
let post: NSString = "data=\(data)"
let url = NSURL(string: "http://123.56.184.207:8080/nurse/login")!
let postData = post.dataUsingEncoding(NSUTF8StringEncoding)!
let postLength = String(postData.length)
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = postData
request.setValue(postLength, forHTTPHeaderField: "Content-Length")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("*/*", forHTTPHeaderField: "Accept")
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.timeoutIntervalForRequest = 120
config.timeoutIntervalForResource = 240
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request) { urlData, response, reponseError in
if let receivedData = urlData {
let res = response as! NSHTTPURLResponse!;
NSLog("Response code: %ld", res.statusCode);
if 200..<300 ~= res.statusCode {
completion(data: receivedData, error: nil)
} else {
let returnedError = NSError(domain: "getSomeStuff", code: 1, userInfo: [:])
completion(data: nil, error: returnedError)
}
} else {
var userInfo: [NSObject: AnyObject] = [:]
if let error = reponseError {
userInfo["message"] = error.localizedDescription
userInfo["cause"] = error
}
let returnedError = NSError(domain: "myFunc", code: 2, userInfo: userInfo)
completion(data: nil, error: returnedError)
}
}
task.resume()
}
postSomeStuff("yoyo") { data , err in
if let data = data { print(data) }
if let err = err { print(err) }
}
let sema = dispatch_semaphore_create(0);
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
// Used only in Playground
XCPSetExecutionShouldContinueIndefinitely(true)

Related

401 response when calling a 307 redirect server

I have built an iOS app calling a server which only accepts calls from whitelisted IPs (client's security requirement). They have now setup a 307 temporary redirect. I have changed the original root URL to the new redirect address and I am now getting 401 - Unauthorised access errors. Nothing else in the code has changed except for the Urls. I have tested using Postman and the calls work with the redirect address. Does anyone know what is causing this issue? I suspect that the HTTP header is being corrupted and the bearer token lost somewhere in the process.
Here is the HTTP response:
<NSHTTPURLResponse: 0x600003315840> { URL: https://"API URL HERE" } { Status Code: 401, Headers {
"Access-Control-Allow-Origin" = (
"*"
);
"Content-Length" = (
0
);
Date = (
"Wed, 06 Mar 2019 13:50:30 GMT"
);
Server = (
""
);
"Www-Authenticate" = (
Bearer
);
"X-XSS-Protection" = (
"1; mode=block"
);
} }
This is the API caller function:
func callAPI(jsonData: Data, childUrl: String, completionHandler: #escaping (_ success: Bool, _ data: Data, _ response: HTTPURLResponse) -> Void) {
let access_token = cache.access_token
let networkHeaders = [ "Content-Type": "application/json", "Authorization": access_token, "cache-control": "no-cache" ]
print(access_token)
let dataResponse = Data()
let urlResponse = HTTPURLResponse()
guard let url = URL(string: config.rootAPIUrl + childUrl) else { return }
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.httpBody = jsonData
request.allHTTPHeaderFields = networkHeaders
let session = URLSession.shared
session.dataTask(with: request) { data, response, error in
if error != nil {
DispatchQueue.main.async {
completionHandler(false, dataResponse, urlResponse)
}
}
if let response = response as? HTTPURLResponse, let data = data {
DispatchQueue.main.async {
completionHandler(true, data, response)
}
}
}.resume()
}
After lots of research and help from Apple. The problem was caused by the 'Authorization' value being lost from the header. The solution was to implement a redirect delegate and reattaching the header values. Here's the working code
func callAPI(jsonData: Data, childUrl: String, completionHandler: #escaping (_ success: Bool, _ data: Data, _ response: HTTPURLResponse) -> Void) {
self.jsonData = jsonData
let access_token = cache.access_token
let networkHeaders = [ "Content-Type": "application/json", "Authorization": access_token, "cache-control": "no-cache" ]
let dataResponse = Data()
let urlResponse = HTTPURLResponse()
guard let url = URL(string: config.rootAPIUrl + childUrl) else { return }
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.httpBody = jsonData
request.allHTTPHeaderFields = networkHeaders
let configuration = URLSessionConfiguration.default
var session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.dataTask(with: request) { data, response, error in
if error != nil {
DispatchQueue.main.async {
completionHandler(false, dataResponse, urlResponse)
}
}
if let response = response as? HTTPURLResponse, let data = data {
DispatchQueue.main.async {
completionHandler(true, data, response)
}
}
}.resume()
}
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: #escaping (URLRequest?) -> Void) {
let access_token = cache.access_token
let networkHeaders = [ "Content-Type": "application/json", "Authorization": access_token, "cache-control": "no-cache" ]
guard let url = request.url else { return }
guard let jsonData = self.jsonData else { return }
var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "POST"
request.httpBody = jsonData
request.allHTTPHeaderFields = networkHeaders
completionHandler(request)
}

Swift-4 : How to fetch data using POST request with Parameters in URLSession with "Content-Type" : "application/x-www-form-urlencoded"

Friends, I've gone through lot's of examples, which are available on S.O. Though I haven't received proper answer, and still I'm facing issue in getting data via api request using URLSession with Post request & passing parameters with it.
First, I'ld like to show you, what I have. tried till now...
func requestApiCall(){
let renewal_id = ""
let policy_no = ""
let client_name = ""
let client_id = ""
let product_name = ""
let created_date_from = ""
let created_date_to = ""
let policy_expiry_from = ""
let policy_expiry_to = ""
self.parameters = ["renewal_id":renewal_id,"policy_no":policy_no,"client_name":client_name,"client_id":client_id,"product_name":product_name,"created_date_from":created_date_from,"created_date_to":created_date_to,"policy_expiry_from":policy_expiry_from,"policy_expiry_to":policy_expiry_to]
let config = URLSessionConfiguration.default
config.httpAdditionalHeaders = [
"Accept" : "application/json",
"Content-Type" : "application/x-www-form-urlencoded"
]
let session = URLSession(configuration: config)
let Url = String(format: "http://myapi-url");
let serviceUrl = URL(string: Url)
var request = URLRequest(url: serviceUrl!)
print(request.url!)
request.httpMethod = "POST"
request.timeoutInterval = 60
request.httpBody = try! JSONSerialization.data(withJSONObject: parameters!, options: [])
let task = session.dataTask(with: request as URLRequest, completionHandler: {data, response, error -> Void in
if error == nil{
print(response!)
}
else {
print(error?.localizedDescription as Any)
}
print(response!)
guard let httpResponse = response as? HTTPURLResponse, let receivedData = data
else {
print("error: not a valid http response")
return
}
switch (httpResponse.statusCode)
{
case 200: //The request was fulfilled
let response = NSString (data: receivedData, encoding: String.Encoding.utf8.rawValue)
if response == "SUCCESS"
{
print("Network - HandShaking Successfull...!!!")
}
else{
print("Network - HandShaking is not successfull...!!!")
}
case 400:
print("response-status - 400 : The request had bad syntax or was inherently impossible to be satisfied.")
case 500:
print("\nresponse-status - 500 : Internal Server Error...!!!")
default:
print("response-status - Unknown : Received Response => \(httpResponse.statusCode)")
}
})
task.resume()
}
After running above function, I'm getting httpResponse.statusCode = 500
But when I run this in postman, I get response properly, as aspected.
Postman Api-Request
Also I have tried to generate code-snippets through postman...which are as follow...
func postmanSnippetApiCall(){
let headers = [
"Content-Type": "application/x-www-form-urlencoded",
"cache-control": "no-cache",
"Postman-Token": "5d571157-86c5-4eac-ba6d-b00779ae5dbd"
]
let postData = NSMutableData(data: "renewal_id=".data(using: String.Encoding.utf8)!)
postData.append("&policy_no=".data(using: String.Encoding.utf8)!)
postData.append("&client_name=".data(using: String.Encoding.utf8)!)
postData.append("&client_id=".data(using: String.Encoding.utf8)!)
postData.append("&product_name=".data(using: String.Encoding.utf8)!)
postData.append("&created_date_from=".data(using: String.Encoding.utf8)!)
postData.append("&created_date_to=".data(using: String.Encoding.utf8)!)
postData.append("&policy_expiry_from=".data(using: String.Encoding.utf8)!)
postData.append("&policy_expiry_to=".data(using: String.Encoding.utf8)!)
postData.append("&undefined=undefined".data(using: String.Encoding.utf8)!)
let request = NSMutableURLRequest(url: NSURL(string: "http://myapiurl")! as URL,
cachePolicy: .useProtocolCachePolicy,
timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse)
}
})
dataTask.resume()
}
But in postman generated code snippet, I'm receiving error on this line i.e request.httpBody = postData as Data and error is this one : Cannot convert value of type 'NSMutableData' to type 'Data' in coercion
If I use thirdParty Library i.e Alamofire, then I'm able to get data very easily.
Alamofire code snippet...runs perfectly..& gives proper response.
func apiRequestByAlamofire(){
let urlString = "http://myapiurl"
let params: [String: Any]? = ["renewal_id":"","policy_no":"","client_name":"","client_id":"","product_name":"","created_date_from":"","created_date_to":"","policy_expiry_from":"","policy_expiry_to":""]
Alamofire.request(urlString, method: .post, parameters: params).responseJSON { response in
print(response) //Here getting perfect response successfully...!!!
}
}
But still I'm struggling this via URLSession...!!!
And still I doubt, that why I'm getting too much problems, while doing with URLSession.
Friends for above my doubt, please I'm open to your suggestions, as well as please help me out to understand it.
Don't know, where am I going wrong. please help me out here.
After searching and fighting a lot with this I have come up with this solution:
guard var components = URLComponents(url: URL(string: "http://example.com")!, resolvingAgainstBaseURL: true)
else { fatalError("Couldn't create URLComponents") }
components.queryItems = params.map { k, v in URLQueryItem(name: k, value: v) }
var request = URLRequest(url: baseUrl.appendingPathComponent(path.rawValue))
request.httpBody = Data(components.query!.utf8)
request.httpMethod = "POST"
The "example.com" can literally be that, because I'm just using URLComponents to encode the parameters.
I am giving you simple function, You can edit this function as per your requirement. You can change your URL and params as well. And in the response, I have written two-line if you are taking JSON array from the server then use the first one if you are taking object then second one else remove Both lines.
func abc() {
let request = NSMutableURLRequest(url: URL(string: "Your URL")!)
request.httpMethod = "POST"
let postString = "param_name_one=\( value_1 )&param_name_two=\(value_2)&........."
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if(error != nil){
// Show Error Message
} else{
do {
//For JSON ARRAY
let jsonItem = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSArray
let json = jsonItem[0] as AnyObject
//For JSON object
let json_object = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as AnyObject
print(json_object)
} catch {
}
}
}
task.resume();
}

Swift http error -1004

I am getting error while making POST request with swift 4(iOS)
I am getting following debug description:
2017-11-09 23:12:57.283421+0300 ios1[35428:5830006]
Task <23DDE1DF-B58F-4A9E-9BB1-21571EE25661>.<1> HTTP load failed (error code: -1004 [1:61])
My code:
let dict = ["link": web.text, "addr": edit.text]
guard let uploadData = try? JSONEncoder().encode(dict) else { return }
let actInd = showActivityIndicatory(uiView: appView)
let url = URL(string: host)!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.uploadTask(with: request, from: uploadData) { data, response, error in
if error != nil {
// handle the transport error
result = 2
print(error.debugDescription)
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 201 else {
result = 1
return
}
if response.mimeType == "text/plain" || response.mimeType == "text/plain", let data = data {
result = 0
print(data)
}
}
task.resume()
P.S.: I could see that request has been done correctly on server.
Thank you a lot

Error 406 uploading image to server from swift ios

I am trying to upload an image from my iOS app written in swift and tried some codes I found about it but nothing works.
Uploading throung Postman works perfect. Here a screenshot of the request in Postman:
Uploading image with Postman
As you can see the API expects a the PUT request with a JSON with only one field called "avatar" and then the image in it. Also keep in mind the form-data. In the Headers I only send the token to do the authentication.
Said this, in the Swift code I try to send as params the array with only the "avatar" key with the image encoded:
func uploadImage(url: String){
let httpMethod: String = "PUT"
var token = getTokenFromNSUserDefaults()
var imageDataJpeg = UIImageJPEGRepresentation(self.myImage, 0.9)
var base64StringJpeg = imageDataJpeg.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) // encode the image
var base64StringJpeg2 = imageDataJpeg.base64EncodedStringWithOptions(nil) // encode the image
var imageDataPng = UIImagePNGRepresentation(self.myImage)
var base64StringPng = imageDataPng.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) // encode the image
var base64StringPng2 = imageDataPng.base64EncodedStringWithOptions(nil) // encode the image
// API Request
self.request(httpMethod, token: token, params:["avatar":base64StringPng2], url: url) { (succeeded: Bool, msg: String) -> () in
var alert = UIAlertView(title: "Success!", message: msg, delegate: nil, cancelButtonTitle: "Okay.")
if(succeeded) {
println("Success")
}
else {
println("Fail")
}
// Move to the UI thread
dispatch_async(dispatch_get_main_queue(), { () -> Void in
})
}
}
//// API REQUEST ////
func request(httpMethod: String, token: String, params: Dictionary<String, AnyObject>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = httpMethod
var err: NSError?
if token != ""{
request.addValue("JWT \(token)", forHTTPHeaderField: "Authorization")
}
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
////Option 1
request.addValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
request.addValue("multipart/form-data", forHTTPHeaderField: "Content-Disposition")
request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
////Option 2
//request.addValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
//request.addValue("multipart/form-data", forHTTPHeaderField: "Content-Disposition")
//request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
println("Response: \(response)")
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var msg = "No message"
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(0), error: &err)
println("JSON: \(json)")
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON1: '\(jsonStr)'")
postCompleted(succeeded: false, msg: "Error")
}
else {
self.parseJson(json!)
postCompleted(succeeded: true, msg: "Works!")
return
}
})
task.resume()
}
Here's the log response from the server with always a 406 error message as follows (do not look at the "censored" url):
Response: <NSHTTPURLResponse: 0x7f967bed1450> { URL: https://***********************/ } { status code: 406, headers {
Allow = "GET, PUT, DELETE, HEAD, OPTIONS";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Wed, 02 Dec 2015 18:30:13 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
"Transfer-Encoding" = Identity;
Vary = Accept;
"X-Frame-Options" = SAMEORIGIN;
} }
Body: Optional()
JSON: nil
The operation couldn’t be completed. (Cocoa error 3840.)
Error could not parse JSON1: 'Optional()'
Fail
Thank you very much for your help in advance!
Your "params" is not in JSON format - the curly braces for JSON dictionary are missing.

Uber Invalid OAuth 2.0 credentials provided Uber Authentication In ios Swift

I'm implementing the Uber's Request Endpoint in my iOS (Swift) App. The Request API/Endpoint requires the user authentication with the app, here is the doc.
For this I'm using this Oauth2.0 library
What I did is
successfully integrated the Library in my project (xCode) with the help of given installation instructions.
In My AppDelegate
let uber_OAuth_Settings = [
"client_id": "XXXXXXX9vtKzobvXXXXXX",
"client_secret": "EXXXXXXXXyFUNCa_Wez6AXXXXXXXnrXtxus",
"authorize_uri": "https://login.uber.com/oauth/authorize",
"token_uri": "https://login.uber.com/oauth/token",
"redirect_uris": ["jamesappv2://oauth/callback"], // don't forget to register this scheme
] as OAuth2JSON
var oauth:OAuth2CodeGrant!
in my method didFinishLaunchingWithOptions of Appdelegate
oauth = OAuth2CodeGrant(settings: uber_OAuth_Settings)
oauth.viewTitle = "Uber Login Service" // optional
oauth.verbose = true // For Logs
Don't forget to register url scheme i.e ("redirect_uris": ["jamesappv2://oauth/callback"])
goto your app's Target -> info Tab -> Url Types -> Click (+), image attached
In AppDelegate add method given Below and Handle the Callback Url
func application(application: UIApplication,
openURL url: NSURL,
sourceApplication: String?,
annotation: AnyObject?) -> Bool {
// you should probably first check if this is your URL being opened
var splitUrl = url.absoluteString!.componentsSeparatedByString(":")
if splitUrl[0] == ("jamesappv2") {
oauth.handleRedirectURL(url)
}
return true
}
Now in my viewController I did like this on myBtnClick
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let url = appDelegate.oauth.authorizeURL()
UIApplication.sharedApplication().openURL(url)
appDelegate.oauth.onAuthorize = { parameters in
println("Did authorize with parameters: \(parameters)")
self.navigationController?.pushViewController(self.PersonalDriverUber_VC, animated: true)
//On Authorization Goto another ViewController using pushViewController of navigationcontroller Method
}
appDelegate.oauth.onFailure = { error in // `error` is nil on cancel
if nil != error {
println("Authorization went wrong: \(error!.localizedDescription)")
}
}
Here is my debug log, I'm getting the valid response:
OAuth2: Handling redirect URL jamesappv2://oauth/callback?state=4B0EB812&code=0sXXXXXXTX7yEbS1XXXXXHuw
OAuth2: Successfully validated redirect URL
OAuth2: Authorizing against https://login.uber.com/oauth/token?state=38158941&grant_type=authorization_code&code=0sXXXXXXXX1jxTrdFQT9Huw&client_secret=EIXXXXXXXNCa_Wez6XXXXXw0BlnrXtxus&client_id=fXXXXXXXy2LOUo9vtKXXXXXQ1nUDO&redirect_uri=jamesappv2%3A%2F%2Foauth%2Fcallback
OAuth2: Exchanging code 0swNXXXXX7yXXXXXXdFQT9Huw with redirect jamesappv2://oauth/callback for token at Optional("https://login.uber.com/oauth/token")
OAuth2: Did receive access token: Dfq3XXXXXXuWgpaqFXXXXXXXgXW, refresh token: EmStT7FEXHRMlS8odPzs1nsha0ObjK
Did authorize with parameters: [token_type: Bearer, expires_in: 2592000, access_token: XXXXXXOZuWgXXXXXXXXuJYOmgXW, refresh_token: EXXXXXHRMlS8oXXXXXXXa0ObjK, scope: profile, last_authenticated: 1430121470]
Notice I'm getting the valid access_token
Here I'm stuck
As per DOCs says in STEP4 *USE BEARER TOKEN
Pass the access_token returned in the response in the Authorization header with the type Bearer to make requests on behalf of a user.*
curl -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' 'https://api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823'
I am not getting the point. How should I pass the access_token in Header with type Bearer? I have done like below
func callRequestAPI(url:String){
let request = appDelegate.oauth.request(forURL: NSURL(string:url)!)
request.HTTPMethod = "POST"
let postString = "product_id="+selectedUberProductId+"&start_latitude="+start_lat+"&start_longitude="+start_lng+"&end_latitude="+end_lat+"&end_longitude="+end_lng
println(postString)
let tempData: NSData = appDelegate.oauth.accessToken.dataUsingEncoding(NSUTF8StringEncoding)!
let base64LoginString = tempData.base64EncodedStringWithOptions(nil)
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("Bearer \(base64LoginString)", forHTTPHeaderField: "Authorization")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { data, response, error in
if error != nil {
println("error=\(error)")
return
}
println("response = \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString = \(responseString)")
}
task.resume()
}
but I'm getting following response
response = <NSHTTPURLResponse: 0x1a284b50> { URL: https://sandbox-api.uber.com/v1/requests } { status code: 401, headers {
"Content-Length" = 75;
"Content-Type" = "application/json";
Date = "Mon, 27 Apr 2015 10:22:01 GMT";
Server = nginx;
"Strict-Transport-Security" = "max-age=31536000; includeSubDomains; preload";
"x-uber-app" = "uberex-sandbox";
"x-xss-protection" = "1; mode=block";
} }
responseString = Optional({"message":"Invalid OAuth 2.0 credentials provided.","code":"unauthorized"})
Finally I have done it :)
I changed the method like below and it Worked
func callRequestAPI(url:String){
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration)
let params:[String: AnyObject] = [
"product_id" : selectedUberProductId,
"start_latitude" : start_lat,
"start_longitude" : start_lng,
"end_latitude" : end_lat,
"end_longitude" : end_lng]
let request = appDelegate.oauth.request(forURL: NSURL(string:url)!)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, error: &err)
let task = session.dataTaskWithRequest(request) {
data, response, error in
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode != 202 {
println("response was not 202: \(response)")
return
}
}
if (error != nil) {
println("error submitting request: \(error)")
return
}
// handle the data of the successful response here
var result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as! NSDictionary
println(result)
if let request_id: String = result["request_id"] as? String{
println(request_id)
}
if let driver: String = result["driver"] as? String{
println(driver)
}
if let eta: Int = result["eta"] as? Int{
println(eta)
}
if let location: String = result["location"] as? String{
println(location)
}
if let status: String = result["status"] as? String{
println(status)
}
if let surge_multiplier: Int = result["surge_multiplier"] as? Int{
println(surge_multiplier)
}
if let vehicle: String = result["vehicle"] as? String{
println(vehicle)
}
}
task.resume()
}
here is the Response I Got, Parsing is also given in my above method
{
driver = "<null>";
eta = 15;
location = "<null>";
"request_id" = "ea39493d-b718-429f-8710-00a34dcdaa93";
status = processing;
"surge_multiplier" = 1;
vehicle = "<null>";
}
Enjoy
Updated for Swift 2. I used the same setup and library for oauth that Qadir describes in his question. I updated his request to work in Swift 2. Hope this helps others.
uberRequest:
let params:[String:AnyObject] = [
"product_id" : uberProduct,
"start_latitude" : userLat,
"start_longitude" : userLng,
"end_latitude" : barLat,
"end_longitude" : barLng]
let urlPath = "https://sandbox-api.uber.com/v1/requests"
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration)
guard let endpoint = NSURL(string: urlPath) else { print("Error creating endpoint");return }
let request = appDelegate.oauth.request(forURL: NSURL(string:urlPath)!)
request.setValue("application/json; charset=utf-8", forHTTPHeaderField:"Content-Type")
request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)
request.HTTPMethod = "POST"
print("Prepare to make request -> \(request)")
let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
if error != nil{
print("Error -> \(error)")
return
}
do {
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
print("Result -> \(result)")
} catch {
print("Error -> \(error)")
}
}
task.resume()
It returns:
Result -> Optional(["driver": <null>, "request_id": 5834384c-7283-4fe6-88a7-e74150c6ab30, "surge_multiplier": 1, "location": <null>, "vehicle": <null>, "status": processing, "eta": <null>])
To use the token just follow step 5 of the instructions in the OAuth2 library, like you did before you started to try to sign it yourself a second time. The request has already been signed and has the Bearer token set up, there is nothing left to do for you:
let url = NSURL(string: "https://api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823")
let req = appDelegate.oauth.request(forURL: url)
// customize your request, if needed. E.g. for POST:
req.HTTPMethod = "POST"
// send the request
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(req) { data, response, error in
if nil != error {
// something went wrong
}
else {
// check the response and the data
// you have just received data with an OAuth2-signed request!
}
}
task.resume()

Resources