Before today's iOS 8.3 update I had my code working right, but after updating server started rejecting requests as it could not find JSON data.
I found that iOS is sending a wrong application/x-www-form-urlencoded text (not properly encoded as it seems a JSON object):
This is what I expected to be sent (and what was sent on 8.2):
As I said, this only happens on iOS 8.3 (I just tried on iOS simulator with 8.2 and it works).
I think the problem is in one of the classes that appear on these lines:
NSData *bodyData = [NSJSONSerialization dataWithJSONObject:requestDict options:0 error:nil];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPBody = bodyData;
I checked Apple documentation and none appears as modified recently.
Is someone suffering the same or knows what can lead to this?
Thanks.
I also have encountered this problem in one application.
It looks like it could be a bug introduced in iOS 8.3. From the official Framework Reference, it is said of the NSURLSessionConfiguration's HTTPAdditionalHeaders property:
This property specifies additional headers that are added to all tasks within sessions based on this configuration. For example, you might set the User-Agent header so that it is automatically included in every request your app makes through sessions based on this configuration.
From what I understand, a Content-Type set in this configuration should be automatically included in every request made through this session, which is no longer the case since 8.3. I've filed a radar.
UPDATE: The radar has been set as 'duplicate' of another so it's more likely a bug.
As Luca pointed out, the work around is to set the Content-Type directly on the request:
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
Source: https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLSessionConfiguration_class/#//apple_ref/occ/instp/NSURLSessionConfiguration/HTTPAdditionalHeaders
I put the comment as answer here:
Try to indicate the http method like
[request setHTTPMethod:#"POST"]
and / or, the request length
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
and / or the content type
[request setValue:#"application/<YOUR CONTENT TYPE>"forHTTPHeaderField:#"Content-Type"];
It seems that iOS 8.3 introduces this. At my site we got found the problem that the (json)body was correctly not set inside the request.
When debugging try to debug the server-side also
Related
I am developing an video sharing app. When I am trying to upload videos larger than 10MB NSURLConnection get lost and I got error NSURLErrorDomain Code=-1005 "The network connection was lost." . Video, less than 10 MB are uploading.Can resolution of video be an issue here?? Resolution of my video is 1280*720 .
Can anyone help me to understand issue here. This is my code for connection
NSString *urlString = [[NSString alloc]initWithString:[NSString stringWithFormat:WEBSERVICE_URL]];
urlString=[urlString stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:100];
[request setHTTPMethod:#"POST"];
This is not duplicate of NSURLConnection GET request returns -1005, "the network connection was lost" because
I am not using third party library for connection and not using simulator. I had tried every thing from that answer.
You might be hitting various timeouts—either the NSURLConnection timeout or a timeout on the server side. iOS may ignore the timeout value you specify, BTW. Or you could just be losing the network connection because your device decided to power down the cellular or Wi-Fi hardware to conserve power. Hard to say which. Or your Wi-Fi connection could have dropped because it missed too many beacons from the access point for some reason. Or....
My advice would be to upload large files a piece at a time, and then assemble the pieces on the server. That way, when (not if) the connection fails, you can re-upload the chunk that only partially transferred, and then continue uploading additional chunks until you've uploaded the whole thing.
See also the Content-Range HTTP header. Obviously, this requires your server-side code to support that functionality, but it is worth the extra effort. :-)
BTW, you forgot to set the Content-Type header.
I have been struggling with an issue where NSURLConnection calls instantly fail. The device needs to be rebooted entirely or Flight Mode needs to be toggled on/off to resolve the problem. Restarting the app (swipe up) alone does not help.
Some facts:
-All URLs are HTTPS, TLS 1.2 compatible with Forward Secrecy. There are no issues with ATS and iOS 9. The error has been present since iOS 7 and remains on 9.2.
-No third party frameworks are used by the app. I use only native NSURLConnection calls that always work, except for when this odd situation occurs.
-No infrastructure/network issues - other devices on same networks (same WiFi for instance) work in the same app at the same time. Going to/from 3G/Wifi makes no difference.
-I always implement willCacheResponse to return nil.
-The service is hosted on AWS Elastic Beanstalk, so some suggested that it might be a DNS caching issue in case of IP address changes - this seems unlikely to me and should trigger multiple errors at once on different devices, which I have never seen.
-The method called is didFailWithError, instantaneously, as if there were no Internet connection on the device at all - all other apps work, however.
-The website that hosts the API used by the app can be browsed with no problems at all times. The website actually makes the same requests to fetch data.
The error code returned is -1003, kCFURLErrorCannotFindHost. I've been following a thread on Git dealing with the same issue to no avail. https://github.com/AFNetworking/AFNetworking/issues/967
I tried using NSURLRequestReloadIgnoringCacheData for all my requests, but that did not help.
With this information, will anyone care to venture a guess what I might be doing wrong? I added the bounty because I have no idea how to approach this problem - especially because it's so inconsistent. And it is definitely not a legitimate error (that is, that the domain could not be found), as the service is operating fine while this happens on random clients.
I create my request with a static method that looks like this. It's been stripped of some non-public info, but basically it just performs a POST request with JSON data. [Controller getSQLHost] just returns a URL - the base domain.
+(NSURLConnection*)initiatePOSTwithJSONDictionary:(NSDictionary*)dictionary toURL:(NSString*)urllocation withDelegate:delegate {
NSMutableDictionary *connectionDictionary = [[NSMutableDictionary alloc] init];
if (dictionary) {
[connectionDictionary setObject:dictionary forKey:#"input"];
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:connectionDictionary options:kNilOptions error:nil];
NSURL *url = [NSURL URLWithString:[[Controller getSQLHost] stringByAppendingString:urllocation]];
NSString *postLength = [NSString stringWithFormat:#"%i", (int)[jsonData length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:jsonData];
return [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
}
Does you delegate implement connectionShouldUseCredentialStorage ? (or respond with YES)
I think the device's keychain is used when this method returns yes which may explain the persisting failure beyond the life time of the running application and why rebooting or otherwise resetting network connectivity "fixes" it. If an authentication failure has been recognized once, it may linger in the key chain for a little while which would then respond immediately without actually going to the server.
What would cause the authentication to register as a failure in the keychain in the first place may depend on a variety of factors. It could be as simple as a typo in the saved password or more convoluted such as some certificate expiration preventing the SSL layer from establishing a secure link.
You're creating NSURLConnections on the current runloop. How many are active at any one time? Have you considered using an NSOperationQueue so that you don't get bitten by load bugs?
Is your delegate thread-safe? If not, that could explain the sporadic-ness of the bug.
You say you don't see the problem often, but others do. Can you borrow their devices and maybe even them and their usage patterns and thus get to see the problem more often?
I get this error when I try running the app on a device. I do not get this error when I run it on the simulator and the post request works fine. This is code snippet I have:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:300.f];
[request setHTTPMethod:#"POST"];
NSData* data = [paramString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:data];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
Any help is appreciated. Thanks
With Xcode 11.2.1, working on a macOS project, I had the same issue.
The fix here was:
Click on project in project explorer
Select the Signing & Capabilities tab
Check "Network: Outgoing connections (client)" checkbox in the AppSandbox section
This error would typically suggest a DNS related issue. Check the DNS settings on your device and confirm you can browse the internet using Safari or another browser (double check by visiting a site you have not visited before to ensure it is not cached).
If there is a url you can GET (instead of POST) on the same server, try visiting it directly in Safari on the device.
The simulator uses your computers network connection, so I recommend checking the System Preferences > Network > Advanced > Proxies > Automatic Proxy Configuration : You must disable Automatic conf.
I am developing a content reading app in which some data is displayed in a tale view and respective detail views.
I have already completed the app but there is a small bug.
I am using AFNetworking library for online data load and offline caching.
I have defined caching policy as described by following code:
Reachability *reach = [Reachability reachabilityWithHostname:#"google.com"];
if ([reach isReachable]) {
// Reachable
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
}
else{
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataDontLoad
timeoutInterval:60.0];
}
But, I am having a small problem that if I load some data online and then turn off the internet connection and close the app, and afterwords if I restart the app again in offline mode, the cached data should load but it is not happening.
I also have tried changing the caching policies as defined in this link.
app deployment target : iOS 6.0
devices : universal
xcode version : 6.1
AFNetworking lib version : 2.0
Replace all of the code you posted and just set the request cache policy to NSURLRequestUseProtocolCachePolicy.
As it stands, you're currently making a synchronous reachability query on every request. Either that or worse—it's returning immediately, but always returning before a real reachability state can be determined.
Is there any difference between NSURLRequest class on Mac OS and iOS?
Apparently there is one.
Here how the class description looks on Mac OS:
<NSURLRequest: 0x60000000f290> { URL: http://www.google.com/ }
And here how it looks on iOS:
<NSURLRequest http://www.google.com/>
As it appears there is a big difference for my project as it work perfectly on iOS and connection fails for Mac OS version.
Does anyone know how to make Mac OS app init the NSURLRequest class object exactly the way it does for iOS?
UPD 1
Same code for initialisation of the object for both platforms
NSURLRequest* aRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com/"]];
I tried same to use NSURLRequest in both AFNetworking and NSURLConnection getting same result - successful connection on iOS and 403 error for Mac OS
successful connection on iOS and 403 error for Mac OS
403 is HTTP's Forbidden response. The fact that you're getting a 403 means that a) your request is making a proper HTTP connection, but b) the server doesn't want to talk to you for some reason. A good strategy for diagnosing the issue is to use a proxy like Charles to look at the successful and unsuccessful requests and note the differences. The user agent parameter is one thing that's likely to differ between the two platforms, but you'll probably find other differences as well. Once you know what's different between the two requests, you'll have a better idea of what you need to change to make the failing requests work.