Json Parsing from NSURLResponse in IOS - ios

I am getting response
<NSHTTPURLResponse: 0xa151d20> { URL: http://abcdxyz/api } { status code: 200, headers {
"Content-Length" = 0;
"Content-Type" = "text/html;charset=UTF-8";
Date = "Tue, 11 Nov 2014 06:57:01 GMT";
Server = "Apache-Coyote/1.1";
} }
Now Can u guys please help me hw will i get JSON Object from this Response. Thanks.

Your code looks good to me (except that you're making a synchronous request, but that's beside the point here.) You're getting the status code 200, which means your request was successful. If you didn't get the data you expected in the response, you'll need to check the documentation for this API to see what the expected response should be. It could be that the server returns just a simple "OK" -- which is pretty much what you're getting.
If the docs don't answer your question, try to ask someone who knows about this particular web service.

Related

eTag support using Alamofire 4

I am trying to enable eTag support in my app.
I am using Alamofire 4 in my swift 3 project.
It seems that eTag is transparently handled by URLRequest which Alamofire uses:
NSURLCache and ETags
But it doesn't work.
Here is http header sent by web server:
headers {
Connection = "keep-alive";
"Content-Length" = 47152;
"Content-Type" = "application/json";
Date = "Tue, 06 Dec 2016 22:43:18 GMT";
Etag = "\"ecf38288be2f23f6710cafeb1f344b8c\"";
} })
Do yo have any hint?
Thanks a lot.
By default, caching is ON. If you log HTTP traffic inside your app, you might see cached responses, without the app making requests to server this time.
In case when URLSession decides to return cached response instead of going to server you will see same Date HTTP response header.
To ensure caching is working, you should inspect network packets between your app and server.
This is the default cache policy when using an URLRequest.
If you want to change this behavior and see the "real" response from the network, so that you can handle the eTag and the statusCode by yourself, you just need to change the cache policy to reloadIgnoringCacheData:
var exampleRequest = try! URLRequest(url: route, method: .post, headers: headers)
// This is the important line.
exampleRequest?.cachePolicy = .reloadIgnoringCacheData
Hope this helps someone!

NSURLSession not using cached responses

I am able to see cached responses when I query NSURLCache directly but when I request the same resource through NSURLSession:dataTaskWithRequest it always queries the server and never gives me the cached response, even with internet disabled.
I configure NSURLCache in application:didFinishLaunchingWithOptions like this:
let URLCache = NSURLCache(memoryCapacity: 20 * 1024 * 1024,
diskCapacity: 80 * 1024 * 1024, diskPath: nil)
NSURLCache.setSharedURLCache(URLCache)
Then I am using this code to check the cache and fetch the response:
print("cached response is \(NSURLCache.sharedURLCache().cachedResponseForRequest(request)?.response)")
NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
print("nsurlsession response \(response)")
}.resume()
The result of my debug prints are:
cached response is Optional(<NSHTTPURLResponse: 0x7f809d0ddfe0> { URL: https://api.test.com/stuff } { status code: 200, headers {
"Cache-Control" = "public, s-maxage=600";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Tue, 06 Sep 2016 23:41:24 GMT";
Etag = "\"4800a836fee27c56a3cce1f0f2bddaefa5a7785b\"";
Server = "nginx/1.11.3";
"Transfer-Encoding" = Identity;
"X-RateLimit-Limit" = 60;
"X-RateLimit-Remaining" = 2; } })
nsurlsession response Optional(<NSHTTPURLResponse: 0x7f809d202e50> { URL: https://api.test.com/stuff } { status code: 200, headers {
"Cache-Control" = "public, s-maxage=600";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Tue, 06 Sep 2016 23:51:52 GMT";
Etag = "\"4800a836fee27c56a3cce1f0f2bddaefa5a7785b\"";
Server = "nginx/1.11.3";
"Transfer-Encoding" = Identity;
"X-RateLimit-Limit" = 60;
"X-RateLimit-Remaining" = 52; } })
As you can see, the Cache-Control headers from the server are set to allow caching. I am not doing anything special with my request, just creating a default NSURLRequest with a URL. Each time I trigger the request, the new response gets cached, but it is never retrieved on subsequent requests.
Is there any reason why NSURLSession would not use a response stored in NSURLCache? Is there something I must do to tell NSURLSession to actually look up requests in the cache?
I can't tell you with absolute certainty why the cache isn't being consulted, but I can give you a list of the most likely reasons:
The server did not respond with 304 when queried about the validity of that ETag header (IIRC using a HEAD request).
The request is too big—either relative to the size of the buffer or in absolute terms. The cache should at least be a couple of orders of magnitude bigger than the requests that you would typically cache; anything over about 5% of the cache size will not be cached.
The request method is something other than GET. (Only GET requests are cached unless you monkey with the machinery significantly.)
More than 10 minutes have elapsed (600 seconds isn't very long).
The request was made in a different URL session that has a different backing cache.
The request was made in an ephemeral URL session or a session that for some other reason has no cache.
The session actually is returning the cached response, but you're seeing a request because it is revalidating a little more aggressively than you might expect—possibly because it will reach its maximum age so soon.
Your URL request is getting handled in the background by a custom NSURLProtocol that doesn't respect the cache (e.g. because of some badly behaved third-party networking or advertising framework).
The request had not actually been fully written to the cache when you tried to retrieve it (timing race caused by multiple threads).
I'm probably forgetting several others. With that said, if I'm forgetting them, that probably means that they aren't documented.
So...
If you verify that everything listed above is working as expected, file a bug at bugreporter.apple.com and include enough code to reproduce the problem, along with a packet dump if possible.

Unhelpful HTTP api response from rails

I have an IOS app and I am passing an image with a couple strings to a rails API. I have started getting this error back from the rails. I couldn't find any info on what would be causing this error. I am assuming that it has something to do with passing a larger than average data package (an image)
.
{ status code: 500, headers {
Connection = close;
Date = "Fri, 15 Jul 2016 20:30:01 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
"Transfer-Encoding" = Identity;
}
Should I be trying to solve this problem from a Client (IOS) or Server (Rails/nginx) perspective?
Potentially Helpful Info:
The rails controller api starts with
def image_build
begin
puts "Begin"
But "Begin" is never printed.
EDIT 1
Some more info:
in the IOS these lines have the output below:
print(response)
print(response.description)
print(response.data)
print(response.request)
print(response.response)
output:
SUCCESS:
SUCCESS:
Optional(<>)
Optional(<NSMutableURLRequest: 0x7fa9539506a0> { URL: http://www.example.com/api/image_build })
Optional(<NSHTTPURLResponse: 0x7fa9515c9cd0> { URL: http://www.example.com/api/image_build } { status code: 500, headers {
Connection = close;
Date = "Fri, 15 Jul 2016 20:30:01 GMT";
Server = "nginx/1.4.6 (Ubuntu)";
"Transfer-Encoding" = Identity;
} })
EDIT 2
I believe it is just timing out in a sense. When I remove the rails image upload and just have the IOS send the image over it still doesnt work. But if I tell the IOS to not send the image, the strings pass over successfully. So it only fails when the IOS tries to send the image.
I am not sure you would get the "puts" response, ideally you should use log statements like logger.debug or logger.info and check the log. Depending on which Rails env you are in, if in production it would be log/production.log or log/development.log in development env. It will give you more answers about why you are getting a 500 error.

Azure Mobile Services Active Directory Login unauthorized

My setup is iOS to .NET backend of Azure Mobile Services
I have followed the guide for active directory authentication here http://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-ios-adal-sso-authentication/ which I am trying to get debugging locally hosted on IIS.
I have set the MS_MasterKey and MS_ApplicationKey as noted here in the web.config https://social.msdn.microsoft.com/forums/windowsapps/en-US/23e7163b-dad5-46ae-bf9b-c71ab067e535/microsoftwindowsazuremobileservicesmobileserviceinvalidoperationexception-the-request-could-not?forum=wpdevelop
And have also added the MS_AadClientID and MS_AadTenants key to the appSettings in the web.config also.
I am able to visit http://localhost/MobileService/help and enter the application key for the password and access the help there.
On iOS though, I am authenticating the with ADALiOS library which succeeds with authentication and returns a valid access token for the resource. Although on passing it to the mobile service I get a 401 unauthorised response which I am assuming is due to the application key somehow. With the result I am passing it to the mobile services client as so.
let payload = ["access_token": result.accessToken]
client.loginWithProvider("aad", token: payload) { user, error in
}
Any ideas or suggestions on what is missing and why it is still returning a 401 status from this login call?
EDIT:
The request headers are:
Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
"User-Agent" = "ZUMO/2.0 (lang=objective-c; os=--; os_version=--; arch=iOSSimulator; version=2.0.0.0)";
"X-ZUMO-APPLICATION" = <actual application key here>;
"X-ZUMO-INSTALLATION-ID" = "DB14CBCD-98EA-4014-AD6E-62E0CF02A9D0";
"X-ZUMO-VERSION" = "ZUMO/2.0 (lang=objective-c; os=--; os_version=--; arch=iOSSimulator; version=2.0.0.0)";
The response I get back is:
<NSHTTPURLResponse: 0x7fa882f81240> { URL: http://localhost/MobileService/login/aad } { status code: 401, headers {
"Content-Length" = 0;
Date = "Sun, 09 Nov 2014 22:39:16 GMT";
Server = "Microsoft-IIS/8.0";
"Www-Authenticate" = "Basic realm=\"Service\"";
"X-Powered-By" = "ASP.NET";
} }
EDIT:
Also doing a POST from Fiddler to the login/aad endpoint responds instantly with a 401 response, even having the app key or master key in the header and with or without the access_token body
The problem was in the configuration in web.config. The only way I found this was redoing everything and then diffing the changes
My problem was a trailing space in the value for the key MS_AadAudience key.

AFNetworking 2 - No response body when request fails

I am using AFNetworking 2 for an iOS project consuming a REST API. When requests fail, I am not able to get the body response.
I have seen this SO answer that says it can be retrieved from the userInfo dictionary. Unfortunately in my case I am not getting the NSLocalizedRecoverySuggestion key-value in my userInfo dictionary with the response body. Instead I see a AFNetworkingOperationFailingURLResponseErrorKey key.
My NSError log is
Error Domain=AFNetworkingErrorDomain Code=-1011 "Request failed: bad request (400)" UserInfo=0xbe471a0 {NSErrorFailingURLKey=http://***.com/api/users, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xbc60e80> { URL: http://***.com/api/users } { status code: 400, headers {
Connection = "keep-alive";
"Content-Length" = 85;
"Content-Type" = "application/json; charset=utf-8";
Date = "Thu, 24 Apr 2014 21:36:57 GMT";
"X-Powered-By" = Express;
} }, NSLocalizedDescription=Request failed: bad request (400)}
As you can see from the headers, I am getting "Content-Type" = "application/json; charset=utf-8"; so this other answer doesn't apply either.
Actually the body response in Postman looks like this:
{"errorCode":100,"description":"There is already a registered user with that email."}
The backend is implemented by myself in Node + Express. I am not very experienced in backend development though, so maybe there is something I am missing or that I could change.
Does anyone know why I am not getting the response body in userInfo?
Quoting AFNetworking owner:
(...) the recommended approach is to create a custom response serializer that translates response data in failing cases into NSError objects as appropriate.
You can see this answer on another AFNetworking issue to see how to integrate it with your session manager, and this repository to see how to implement it.

Resources