AFNetworking 2 empty POST response but no errors - ios

It's a very tricky problem:
I do a POST request (login) to a server.
The server will answer:
ok Status Code: 200 + JSON Data
error Status Code: 401 + plain/text
Code:
func login (id: String, password: String){
self.responseSerializer = AFJSONResponseSerializer()
self.responseSerializer.acceptableContentTypes = nil
self.responseSerializer.acceptableStatusCodes = NSIndexSet(index: 400)
//self.responseSerializer.acceptableStatusCodes = nil
var param = ["id": lbid, "password": password]
POST(APIURL.URL_LOGIN, parameters: param,
{ (operation : NSURLSessionDataTask!, response : AnyObject!) -> Void in
//var finalResponse : Dictionary = Dictionary<String, String>()
var tmp = response as String
self.defaults.setObject(tmp, forKey: "USERSSID")
self.defaults.setBool(true, forKey: "USERLOGGEDIN")
println("Success login")
}) { (operation : NSURLSessionDataTask!, error : NSError!) -> Void in
println(error)
}
}
It executes the failure blog and I get this error:
Code=-1011 "Request failed: no error (200)" UserInfo=0x7f9fa1534760 {com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7f9fa15791e0> { URL: https://************ } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Length" = 107;
"Content-Type" = "application/json";
Date = "Wed, 04 Mar 2015 21:47:51 GMT";
"Keep-Alive" = "timeout=7, max=150";
Server = Apache;
"Set-Cookie" = "SID=************; expires=Mon, 02-Mar-2020 21:47:51 GMT; path=/;domain=.*********";}},NSErrorFailingURLKey=https://***********,com.alamofire.serialization.response.error.data=< CORRECT POST BODY>, NSLocalizedDescription=Request failed: no error (200)}
If I delete this code:
self.responseSerializer.acceptableStatusCodes = NSIndexSet(index: 400)
Then the app crashes. However the server responses with status code 200...
I don't know how to solve this issue.
Could you help me?
Here I get the correct body. But why not in the normal success blog?
EDIT:
self.responseSerializer.acceptableStatusCodes = NSIndexSet(index: 200)
=> App crashs
self.responseSerializer.acceptableStatusCodes = nil
=> App crashs
self.responseSerializer.acceptableStatusCodes = NSIndexSet(index: 401)
=> App doesn't crash, but executes failure block. Status code in error message is 200 and error data contains the correct POST response body.
=> I could extract the message from the error data... but it's such a simple task. It has to work correctly.
Can't use Alamofire because I want to use ssl certificats!
Final edit:
Don't no why, but the error disappeared by its own.

If you haven't already done so, check out Postman (a Google Chrome app). That's the best way to debug AFNetworking issues, by simulating the same request and making sure the data is coming through properly. A number of times, I've been fighting an issue to then use Postman and discover that it's something the server is doing.

I found something that said:
acceptableStatusCodes
The acceptable HTTP status codes for responses. When non-nil,
responses with status codes not contained by the set will result in an
error during validation.
In Objective C:
self.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];

The previous post was very useful to fix it. I was searching more and more but nothing was helped out. I tried of adding different codes and got tired ton's of times. Finally seen the above post, which was really solved the issue. I spent 2 days to find the solution.
Initially got the error with -1011 with 400 error. I solved by using the below:
manager.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndex:400];
Again got different error like this: "200 no error". I solved by using below code:
manager.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
It works!! cool!!
Hence, I advice you you guys to add the set of below code:
manager.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndex:400];
manager.responseSerializer.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
Thanks Stackoverflow!!!!

Related

POST API stopped working in iOS Swift after changing base URL of Rest APIs

I am getting bit complex issue. I have integrated REST APIs in my existing iOS Swift based Application. It works all correctly.
Now we just changed our domain server so the Base URL of the REST APIs shifted & changed. Now what the issue I am getting is after changing the BaseURL my all POST APIs stopped working.
Note :
I did checked in POSTMan it works correctly
I did tested on Android it works correctly
Even GET APIs with changed BaseURL works correctly on iOS
Only POST APIs not working after changing baseURL
Here is the error message I am getting :
statusCode should be 200, but is 500
response = Optional(<NSHTTPURLResponse: 0x282dfd960> { URL: API_BASE_URL/check_social_id } { Status Code: 500, Headers {
Connection = (
close
);
"Content-Length" = (
289
);
"Content-Type" = (
"text/html; charset=iso-8859-1"
);
Date = (
"Mon, 02 Sep 2019 09:41:13 GMT"
);
Server = (
Apache
);
} })
Note that there is no issue with the API code as its still works with the old BaseURL. Everything with the same code if I just change it to the old BaseURL it works correctly. But If I use new URL it gives the error as I stated above.
New Edit :
After some suggestions I have tried to use the Alamofire library & now I am getting some different error message. Here is my code :
import UIKit
import Alamofire
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "API_URL"
Alamofire.request(urlString, method: .post, parameters: ["media_type": "gmail", "media_id":"12121212121", "fname":"mSolu", "email":"demo.test#gmail.com"],encoding: JSONEncoding.default, headers: nil).responseJSON {
response in
switch response.result {
case .success:
print(response)
break
case .failure(let error):
print(error)
}
}
}
}
New error message :
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Garbage at end." UserInfo={NSDebugDescription=Garbage at end.}))
Any suggestions or hint will be highly appreciated.

Getting token from an asp.net web api in iOS / swift

I am a .net developer but very new to iOS and swift development, just need help with consuming Web API using Swift2
The Asp.net Web API has been built with OAuth2 authentication, published to my Azure VM server with SSL certificate installed. The API site itself works properly, tested through Postman
However I got stuck when started writing first few lines of code in Swift trying to get Authentication token. After reading some online tutorials I decided to engage Alamofire, and produced below codes snippet:
func GetToken() {
let params = [
"grant_type" : "password",
"username" : "123456#qq.com",
"password" : "averygoodpassword"
]
let headers = [
"Content-Type" : "application/x-www-form-urlencoded"
]
request(.POST, "https://api.example.com/token",
parameters: params,
headers: headers,
encoding: .JSON)
.responseJSON { request, response, result in
print (request)
print (response?.description)
print (result)
switch result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")
case .Failure(let data, let error):
print("Request failed with error: \(error)")
if let data = data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
}
}
It ends up with below output in Xcode which didn't seem to be OK. The error = unsupported_grant_type told me that the request were sent to server but the parameters were not sent with request properly. I really cannot figure out the reason and solution, had been digging on Internet for a few days but still feeling desperate with it. Can anyone help please? Even if someone can provide a pure swift solution without any 3rd party library will be greatly helpful. Thanks!
Xcode output:
Optional( { URL: https://api.example.com/token })
Optional(" { URL: https://api.example.com/token } { status code: 400, headers {\n \"Access-Control-Allow-Headers\" = \"Content-Type\";\n \"Access-Control-Allow-Methods\" = \"GET, POST, PUT, DELETE, OPTIONS\";\n \"Access-Control-Allow-Origin\" = \"*\";\n \"Cache-Control\" = \"no-cache\";\n \"Content-Length\" = 34;\n \"Content-Type\" = \"application/json;charset=UTF-8\";\n Date = \"Fri, 30 Sep 2016 10:30:31 GMT\";\n Expires = \"-1\";\n Pragma = \"no-cache\";\n Server = \"Microsoft-IIS/8.5\";\n \"X-Powered-By\" = \"ASP.NET\";\n} }")
SUCCESS
Success with JSON: {
error = "unsupported_grant_type";
}
I had a similar problem trying to POST to MailGun for some automated emails I was implementing in an app.
I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
I'm slightly opposed to using 3rd party libraries, especially for small things like a http POST and this seems like a much more maintainable solution to me. Anyways, hope this helps, let me know if you have any questions!

How to tweet with Line Break (Twitter Rest API via Fabric)

I'm developing a application for iOS(Swift).
I'm afraid my expressions may be rude or hard to read, because I'm not so good at English.
Sorry for any inconvinience I may cause you.
I asked same question on Twitter Developer Forums.
I'm trying to make tweet with "Line Break".
For example
Hello!
World!
So I tried to use Rest API via Fabric. But it doesn't work.
My code is...
let endPoint = "https://api.twitter.com/1.1/statuses/update.json"
var clientError : NSError?
var tweetText = self.contentTextView.text
tweetText = tweetText.stringByReplacingOccurrencesOfString("\n", withString: "\n\r")
let params = ["status" : tweetText]
let request = Twitter.sharedInstance().APIClient.URLRequestWithMethod("POST", URL: endPoint, parameters: params, error: &clientError)
Twitter.sharedInstance().APIClient.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
if (connectionError == nil) {
print(“success")
}else {
print(“failure: \(connectionError)")
}
}
In this code, “contentTextView.text" is text which I want to tweet.
I tried to change line break code “\n”,”\r”,”\n\r” and “%0D%0A”, but it didn’t work too.
Error message is...
failure: Optional(Error Domain=TwitterAPIErrorDomain Code=32 "Request failed: unauthorized (401)" UserInfo={NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/update.json, NSLocalizedDescription=Request failed: unauthorized (401), NSLocalizedFailureReason=Twitter API error : Could not authenticate you. (code 32)})
If contentTextView.text doesn’t contain “\n” (in other words single line), I can tweet correctly.
For example
Hello!World!
How can I do?
Thanks.
UPDATE:
If I remove the line below, I get same error.
tweetText = tweetText.stringByReplacingOccurrencesOfString("\n", withString: "\n\r")
What if you don't replace "\n"?
By this, I mean remove the line
tweetText = tweetText.stringByReplacingOccurrencesOfString("\n", withString: "\n\r")

Restkit Authorization Header disappears

I already searched everywhere and this issue that should have been trivial is taking longer than I wanted therefore I am reaching you for help.
I am using swift and integrated restkit using cocoapods.
Despite, as you can see the screenshots/log, the header is fine however the outgoing http packet is not consistent.
AppDelegate:
RKlcl_configure_by_name("RestKit/Network", RKlcl_vTrace.value);
RKlcl_configure_by_name("RestKit/ObjectMapping", RKlcl_vTrace.value);
ObjectManagerCode:
let objectManager: RKObjectManager = RKObjectManager(baseURL: NSURL(string: Endpoints.BaseUrl.toString()))
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
let username = "TestUser"
let password = "password"
objectManager.HTTPClient.setAuthorizationHeaderWithUsername(username, password: password)
objectManager.HTTPClient.setDefaultHeader("whatIWantForChristmas", value: "You")
objectManager.HTTPClient.allowsInvalidSSLCertificate = true
Request:
var requestUrl = cds.objectManager!.requestWithObject(
nil,
method: RKRequestMethod.GET,
path: endpoint.path,
parameters: endpoint.parameters())
cds.objectManager!.getObjectsAtPath(
endpoint.path,
parameters: endpoint.parameters(),
success:
{
(RKObjectRequestOperation, RKMappingResult) -> Void in
println(RKObjectRequestOperation.description)
Logger.Info("Success");
},
failure: {
(RKObjectRequestOperation, error) -> Void in
Logger.Error("Error: \(error.description)")
println(RKObjectRequestOperation.HTTPRequestOperation.description)
})
Log:
T restkit.network:RKObjectRequestOperation.m:178 GET 'http://website/api?format=json':
request.headers={
Accept = "application/json";
"Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
Authorization = "Basic VGVzdFVzZXI6cGFzc3dvcmQ=";
"User-Agent" = "malaria-ios/1 (iPhone Simulator; iOS 8.3; Scale/2.00)";
whatIWantForChristmas = You;
}
...
E restkit.network:RKObjectRequestOperation.m:576 Object request
failed:Underlying HTTP request operation failed with error:
Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200), got 403"
UserInfo=0x7ff54ae4f690 {NSLocalizedRecoverySuggestion={"detail":"Authentication credentials were not provided."}
What I figured out:
I can send anything in the header as long as it isn't "Authorization", if I change to "Authorization2", ok. The header "WhatIWantForChristmas" is also there. The authorization isn't despite being present in the log! It seems that the underlying software filters.
Out of paranoia I tried turning off firewall, cleaning project, reseting iOS simulator and nada. The application I used to see the HTTP packets is Charles.
What am I doing wrong?
Url for the screenshot pf Charles: http://s7.postimg.org/pfwn7kyq2/Screen_Shot_2015_06_20_at_21.jpg

NSURLConnection, NSURLAuthenticationChallenge failure response

When trying to log in to my app with iOS7 I'm getting a failure response with some description. This is NSLog of NSURLAuthenticationChallenge failureResponse:
<NSHTTPURLResponse: 0xa383570> { URL: <URL> } { status code: 401,headers {
"Content-Length" = 1385;"Content-Type" = "text/html;charset=utf-8";
Date = "Fri, 13 Jun 2014 12:14:24 GMT";
Server = "Apache-Coyote/1.1";
"Www-Authenticate" = "Basic realm=\"booo\"";
"x-errorCode" = 02;
"x-errorDescription" = "com.idealination.core.server.client.http.ServerException:
Request failed: <URL> Status: CLIENT_ERROR_UNAUTHORIZED
Error: #Unauthorized :: Invalid userid or password.";
} }
and I need that last line to know what error do I get. But when I use iOS6 and iPhone 3gs I get only:
<NSHTTPURLResponse: 0x1c507ae0>
What should I do to get a response like using iOS7? And why I'm getting a different response?
You should not be looking for the last line, you should be looking for the HTTP Status Code, in this case 401.
if(urlResponse.statusCode == 401) { }
If you need to convert that into what the status code means as a string use
NSString *status = [NSHTTPURLResponse localizedStringForStatusCode:urlResponse.statusCode];

Resources