11

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.

streem
  • 9,044
  • 5
  • 30
  • 41
  • If you use NSURLSession API, does the issue reproduce? – Léo Natan Aug 02 '15 at 16:45
  • @LeoNatan, yep I have the exact same problem with `NSURLSession` – streem Aug 02 '15 at 17:35
  • What do you see on the server side? Do you see the server accept a client connection or does not even reach the server? I'd say it looks like somewhere in your server, you are dropping the connection. A firewall perhaps. – Léo Natan Aug 02 '15 at 17:37
  • @LeoNatan, well i believe it doesn't reach the server, nothing in logs. (whereas i can see if a client is denied). Also like i mentioned in my post, if i lock the device, the request is sent right after i unlock it. – streem Aug 02 '15 at 17:58
  • Do you have any security measures on one webserver that you don't have on another? – Jojodmo Aug 07 '15 at 17:27
  • @Jojodmo Not that I know of, both URLs are publicly accessible. – streem Aug 07 '15 at 19:23
  • @Justa Maybe your DNS server automatically drops connections that take too long? – Jojodmo Aug 07 '15 at 20:16
  • @Jojodmo hmm how could i check that or make it not drop them ? Also checked my hosting service, and i had a cache poisoning security enabled on the server that was failing. It takes some time to disable it, i'll give updates if there's any change. – streem Aug 07 '15 at 20:53
  • @Justa I'm not sure, but the fact that you can connect via the IP and not the www address makes me think its a problem with the DNS server – Jojodmo Aug 08 '15 at 00:03

4 Answers4

2

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.

djbp
  • 714
  • 8
  • 24
  • Thanks for your answer, karlos suggestion is not working. If i may add also, i have a `Connection:close` header in each response and i believe it's the fact that i use other apps that make the request not go. Like if the OS put my app and its connection in background and forgot to wake it up. – streem Aug 05 '15 at 18:16
  • Did you try adding timeout for https request? – Karlos Aug 05 '15 at 19:24
  • You mean when i init my request ? yes, it has a 120s timeout. – streem Aug 05 '15 at 19:54
  • Just reduce it to 10 seconds and try printing the response. Normally in apps the timeout is around 60 seconds. – Karlos Aug 06 '15 at 05:47
  • @karlos Yep, I increased it to see what happened, at first it was 30 sec at the result was the same. – streem Aug 06 '15 at 07:36
2

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.

streem
  • 9,044
  • 5
  • 30
  • 41
  • "DNSSEC packets may be denied because the response size is too large." Check the link http://www.cisco.com/web/about/security/intelligence/dnssec.html This might be a reason. – Karlos Aug 10 '15 at 13:57
1

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()
}
Kirit Modi
  • 23,155
  • 15
  • 89
  • 112
  • Thanks for your answer, but this is not a timeout duration issue. When it fails, it always fails at the end of the timeout whatever that duration is. – streem Aug 08 '15 at 09:41
0

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

Karlos
  • 1,653
  • 18
  • 36
  • Thanks for your answer, i'm not sure for what reason you posted this code and unfortunately I have the same problem with it. – streem Aug 05 '15 at 18:13
  • I tried the ConnectionBugApp on LTE/4G connection and it working fine for "https://tripaff.com/" and "https://meetsam.co/" URLs. I got error 503 for "http://ip.jsontest.com/" Url. – Karlos Aug 06 '15 at 06:41
  • Hmm, have you tried after using network intensely on other apps ? You can also try by forgetting about the app for a few hours and just hit the Try Connection button again later. – streem Aug 06 '15 at 07:24
  • I tried the reconnecting and its working properly for the "tripaff.com/"; and "meetsam.co/" and error 503 for "ip.jsontest.com/". – Karlos Aug 07 '15 at 05:50