NSURLConnection Error code (-1202,1012) - ios

I am using NSURLConnection for one field service type iOS appliation, so app is field service type there are more then 50 users and more then 50 users may use the application on same time that's why there are more then 50 or 60 request come to the server. Now my issue is I have received below two errors frequently means every single user can face this error more then 5 times in one day. so it become a challenge for me.
The Error Code:
-1202 NSURLErrorServerCertificateUntrusted
-1012 NSURLErrorUserCancelledAuthentication
I have searched a lot and i found that they are server related errors but still i don't have any solution for how to resolve this problem.
Please help me how can i solve this NSURLConnection error (-1202 NSURLErrorServerCertificateUntrusted and -1012 NSURLErrorUserCancelledAuthentication) problem.
Thanks in advance.

You need to use connectionWithRequest:delegate: to accept untrusted certificates.
You can implement these delegate methods
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return YES;
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection
{
return YES;
}

Related

Request not sent

I'm having a weird problem when i consume my API from my app. Sometimes, for no reason, the request is just not sent, and it fails at the end of the time-out with the following error:
Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
I have tried many API such as NSURLConnection delegates, NSURLSession and NSURLConnection.sendSynchronousRequest without success.
Here is a sample project i have made to highlight the issue. ConnectionBugApp
Here are the steps to reproduce:
Run the app in Xcode and stop debug just so the app is on your phone
Open the app, click Test Connection (it succeeds, loading wheel stops spinning right after)
Go to other apps like facebook/twitter/network games (somes that are a bit heavy) and switch to airplane mode a few times
Go back to my app and click Test Connection (loading wheel never stops)
A few details that might help:
If I use my server IP instead of my domain name, it succeeds
Issue only appears when on the LTE/4G network
Any ideas or workaround would be greatly appreciated ! Feel free to ask for more details.
Thanks
EDIT
I've edited the description a lot since i first posted it (hoping to make it cleaner and clearer), i'm sorry if some answers or comment don't really make sense anymore.
I have come across this issue when using an asynchronous request. It seems as though iOS limits the number of open connections to a single domain, such that all subsequent connections fail in the manner you have described.
If connections typically complete quickly, this possibly won't be an issue.
The solution is to limit the number of open connections to the same domain to prevent this from happening.
The answer posted by karlos works because the synchronisity of the connection blocks others from being opened.
Like mentioned in comments, I had DNSSEC (cache poisoning protection) enabled on my hosting service.
Disabling it, fixed the issue, even though that might not be a really nice solution. After a few weeks of searching, that'll be good enough.
I'll give the bounty to someone that can explain it, or who can provide a better solution.
In your code your request take default timeout is 60s, but you can change Request time out in your code as below.
in your NetworkItem class change time out.
init(request:NSMutableURLRequest){
self.request = request
self.request.timeoutInterval = 120
super.init()
}
Try the following code for the connection.This would help you.
let urlData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
if error != nil || urlData!.length == 0
{
println("Error happend timeout======\(error?.code)!")
continue
}
else //else1
{if let httpResponse = response as? NSHTTPURLResponse
{
println("Status Code for successful---\(httpResponse.statusCode)")
// For example 502 is for Bad Gateway
if (httpResponse.statusCode == 502)
{
// Check the response code from your server and break
break
}
else
{
//Your code
}
}
}
You can get the list of HTTPS status code in the following link
StatusCode

Basic Authentication failures with iOS 8

I have an iOS app that interacts with a server running Rails, and has been stable and reliable for 3 years. The server requires Basic and SSL certification, and this has been working perfectly fine right up to and including iOS 7.
However, I am now seeing authentication issues with devices running iOS 8. Devices / simulators running < iOS 8 continue to work fine.
On app initialization, there is a flurry of data requests to sync with the server that need to pass Basic authentication.
These result in the following delegate method being called,
willSendRequestForAuthenticationChallenge
...and the problem occurs because these are being challenged endlessly - the code deliberately fails on the second try when [challenge previousFailureCount] > 0 (the code path follows standard practice by calling cancelAuthenticationChallenge if the previousFailureCount > 0) - see below.
I've logged the challenge ids, and these are different across each challenge, even when the previousFailureCount > 0.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic])
{
if ([challenge previousFailureCount] == 0)
{
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:MY_USERNAME
password:MY_PASSWORD
persistence:NSURLCredentialPersistenceForSession]; // Retain for rest of session
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
// ...error will be handled by connection didFailWithError
}
}
}
If I knock out the call to check the previousFailureCount, there are endless invocations of the challenge method.
However, once this flurry of failures has failed, the subsequent and later 'individual' NSUrlRequests are successfully authenticated.
Again, this problem is specific to iOS 8. Any ideas why a 'fast' succession of authentication requests would fail in iOS 8, but work in iOS 7?
Thanks.
In case you are not handling the authentication method (NSURLAuthenticationMethodHTTPBasic) you must invoke one of these methods anyway:
useCredential:forAuthenticationChallenge:
continueWithoutCredentialForAuthenticationChallenge:
cancelAuthenticationChallenge:
performDefaultHandlingForAuthenticationChallenge:
rejectProtectionSpaceAndContinueWithChallenge:
If you want to ignore a certain authentication method you preferable might want to invoke performDefaultHandlingForAuthenticationChallenge:.
See also: connection:willSendRequestForAuthenticationChallenge:
I have the same issue, I deleted the if([challenge previousFailureCount] == 0) , and it works.
But I don't know why it fails in IOS 8.
The answer / update to this question also fixed the problem I was seeing.
NSURLConnection timing out on iOS8
Again, something changed in iOS 8, requiring this fix.

The joys of didFailLoadWithError UIWebview

If you look at the code here:
https://github.com/evernote/evernote-sdk-ios/blob/master/evernote-sdk-ios/internal/ENOAuthViewController.m
that implement OAuth 2.0 flow in UIWebView.
The author uses this code for the didFailLoadWithError delegate function:
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
if ([error.domain isEqualToString:#"WebKitErrorDomain"] && error.code == 102) {
return;
}
if (error.code == NSURLErrorCancelled) {
// ignore rapid repeated clicking (error code -999)
return;
}
}
Why is he ignoring those two errors (NSURLErrorCancelled) and error code 102?
Error code 102 from the WebKitErrorDomain is the error that is raised by the UIWebView if its delegate returns FALSE from webView:shouldStartLoadWithRequest:navigationType. When implementing the OAuth2 flow with a UIWebView it is common to do this when the final redirection URL is encountered as this means it's time to hide the web view and start the process of exchanging the access code in the URL with an token directly from the authentication provider.
The second error is something I'm less familiar with but based on the code comment provided and the accepted answer to this question, I suspect there's some logic in the browser or UIWebView that automatically filters out fast repeated clicks. The error is probably being raised by design so that delegates can be notified of this if they're interested.
from wiki
102 Processing (WebDAV; RFC 2518) As a WebDAV request may contain many
sub-requests involving file operations, it may take a long time to
complete the request. This code indicates that the server has received
and is processing the request, but no response is available yet.[3]
This prevents the client from timing out and assuming the request was
lost.
from
WebKitErrorDomain A string used by NSError to indicate that the error
was originated by a WebKit class.
looks loke web kit errors are something internal and author do not want to handle this error
UPDATE
do not see that there's && in condition. So that mean that if WebKitErrorDomain appears and code is 102 -- that means that web kit can not show page for now, because there're too many sub-requests and you have to wait a bit

How to make webservice pass errors through NSURLConnection's connection:didFailWithError:?

What does a web service need to do to cause NSURLConnection's delegate to receive the connection:didFailWithError: message?
For example:
iOS app passes a token to the web service, web service looks up the token, and then the web service needs to respond with an error saying "invalid token" or something of the like.
Currently, the data is received, and in "connectionDidFinishLoading:" is parsed for error messages. This means I'm error checking in two places, which I am trying to avoid.
I have both the iOS app and web service completely under my control.
In my experience (the three most dangerous words in programming), -connection:didFailWithError: is only called if the HTTP exchange failed. This is usually a network error or maybe an authentication error (I don't use authentication). If the HTTP message succeeds, no matter the response code, -connectionDidFinishLoading: is called.
My solution: call -connection:didFailWithError: when I detected an error. That way all my error handling code is in one place.
At the top of my -connectionDidFinishLoading:, I have:
NSError *error;
NSDictionary *result = [self parseResultWithData:self.connectionData error:&error];
if (!result) {
[self connection:connection didFailWithError:error];
return;
}
There are many conditions on which the delegate connection:didFailWithError: of NSUrlConnection may invoke.Here's a list of those errors or constants.I think an alertview would be better to show http errors in connection:didFailWithError:.
-(void) connection:(NSURLConnection *)connection didFailWithError: (NSError *)error
{
UIAlertView *errorAlert= [[UIAlertView alloc] initWithTitle: [error localizedDescription] message: [error localizedFailureReason] delegate:nil cancelButtonTitle:#"Done" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
NSLog (#"Connection Failed");
}
While not directly related to your question, I would encourage you to move to a more high level library. I can heartily recommend AFNetworking, it is production ready and I have used it in many projects. This will allow you to inspect the response code of each request in the failure block. This project also abstracts away a lot of the low level handling that you would otherwise be required to write for network communication; I'm speaking here about parsing and creating XML / JSON strings to communicate with a service.
To give you a more focused answer to your question, I would call the cancel method of your NSURLConnection once you have noticed an error in connectionDidFinishLoading:. This will automatically cancel the request and call the failure method of the delegate object.
The documentation for NSURLConnection is pretty dry, and the failure method of the delegate does not specifically document the failure cases. You may be able to find more information in the URL Loading System Programming Guide.
I couldn't see the forrest for the trees.
I needed to step back from connection:didFailWithError: and look at a different delegate method connection:didReceiveResponse:!!
With the web service fully under my control, the endpoint could respond with a 500 status code, which gets picked up in connection:didReceiveResponse, and pass along some JSON further explaining the situation, which gets picked up and processed in connection:didReceiveData:.
The NSURLConnection delegate hangs onto a couple more bits of state throughout the process, but it has the best code smell I've found so far.
Jeffery's answer was by far most correct: the connection:didFailWithError: callback is only in relation to the network failing, any response from the web service means the connection didn't fail!

iOS 5 - connect to an HTTPS server

I am trying to overcome the change done in iOS 5 regarding the NSURLConnection.
Basically the methods changed, so if you need to connect to a site that uses HTTPS and send credentials to authenticate, you cannot do it anymore, because many methods were deprecated.
Is there any place where I can get a working example of how should I write the code to use iOS5 compliant code? I've check the documentation and the headers but not a single source around show me how to make such connection with an example, that shows where the code goes in which file (assume that I just start from a standard template from Xcode, like the single view template or the tab bar template).
I would really appreciate any suggestion; Since my app will run on iOS 5 I would like to use the new procedure, but the lack of documentation and tutorials are making my task harder than what I thought.
You should use the NSURLCredentialStorage singleton. You need to add the credentials to the storage before using NSURLConnection by calling one of the NSURLCredentialStorage methods, for instance:
- (void)setCredential:(NSURLCredential *)credential forProtectionSpace:(NSURLProtectionSpace *)protectionSpace
I use this:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:
(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] <= maxRetryCount ) {
NSURLCredential *newCredential =
[NSURLCredential
credentialWithUser: userName
password:password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender]
useCredential:newCredential
forAuthenticationChallenge:challenge];
}
else
{
NSLog(#"Failure count %d",[challenge previousFailureCount]);
}
}
This works fine for me. However, it looks like self signed certificates are accepted too. I probably need to post a separate question about that.

Resources