17

I'm using the ASIHTTPRequest lib in my iOS app to make RESTful requests to my Rails 3 web app. I seeing a weird and somewhat consistent error the 1st time I try to make a POST request to my web app, but then the POST request works fine the on the second attempt. The exact error is...

Error Domain=ASIHTTPRequestErrorDomain Code=1 "A connection failure occurred" UserInfo=0xb513740 {NSUnderlyingError=0xb5135a0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1005.)", NSLocalizedDescription=A connection failure occurred}

And here's my ASIHTTPRequest code for making the POST request...

    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://myrails3app.heroku.com/tournaments/%d/register.json", tid]];
    __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request setRequestMethod:@"POST"];
    [request addPostValue:username forKey:@"username"];

    [request setCompletionBlock:^
    {
        NSData *responseData = [request responseData];     
        NSLog(@"Success!");
    }];

    // Set the code to be called when the request fails
    [request setFailedBlock:^
     {
         NSError *error = [request error];
         NSLog(@"Error: %@", [error localizedDescription]);
     }];

    // Start the request
    [request startAsynchronous];

It's worth mentioning that when it errors out, it errors out incredibly quickly! Also, for what it's worth, my Rail 3 app that I'm making the POST request to is hosted on Heroku. Your thoughts?

Thanks so much for your wisdom!

BeachRunnerFred
  • 18,070
  • 35
  • 139
  • 238
  • Could be that the network interface isn't active until the first try, which wakes it up for the second try? – Tom Irving May 21 '11 at 15:08
  • I suppose, but since this is occurring on iOS devices, wouldn't every developer using the ASIHTTPRequest lib be seeing this problem? – BeachRunnerFred May 21 '11 at 15:15
  • Just some ideas: Does this issue occur when running the app in the emulator or also when you try it on a device? Do you see the same behavior when you do a synchronous request? If it only occurs when using async requests then it might be interesting to see if the app acts differently on an iPhone/iPad1 (single core processor) vs an iPad2/Emulator (multiple cores). – Volker Voecking May 21 '11 at 15:51
  • This problem occurs in both the simulator and on the iPhone and iPad devices. I'll try performing a synchronous request and report back. – BeachRunnerFred May 21 '11 at 16:01
  • I tried this with startSynchronous and it failed. – BeachRunnerFred May 21 '11 at 16:16
  • @beachrunnerjoe -are seeing a hit on your ruby server for the first attempt? Could your server be returning a 500 or something the first time? – Rayfleck May 21 '11 at 21:50
  • Hey Ray, no I'm not seeing a hit for the first attempt. What does that mean to you? – BeachRunnerFred May 21 '11 at 22:28
  • Hey Ray, the logs show no signs at all of the request, not even a 500 response. Your thoughts? – BeachRunnerFred May 21 '11 at 23:16

4 Answers4

30

This issue I had a lot of hard time to figure out why. The problem resides in ASIHTTPRequest itself (iOS), not the rails code.

To make a long story short, the problem is specific to the use of persistent connection for every request sent by ASIHTTPRequest.

While this is good for GET requests, most server implementation does not allow persistent connection to be used with POST request.

I didn't really have time to investigate it deeply on the server side of things but I think that the problem resides with the 100-Continue header that should be sent (and which isn't) with request that has body attached to it (hence PUT/POST). If you want to have a deeper look at what I'm talking about go have a read at the spec sheet: http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

So the persistent connection used by ASIHTTPRequest wait for a 100 response to be sent, which is never sent. so it ends up being timed out.

A fix is to set persistentConnection to NO with your post requests like the following:

ASIHTTPRequest *req                     = [ASIHTTPRequest requestWithURL:url];
req.shouldAttemptPersistentConnection   = NO;
Pier-Olivier Thibault
  • 3,907
  • 2
  • 33
  • 33
  • Also, I found out that using thin gives me much more stable performance with request. so you might want to use that instead by calling `rails s thin` – Pier-Olivier Thibault May 23 '11 at 13:27
  • 5
    As of v1.8.1, ASIHTTPRequest doesn't use persistent connections for requests with a body (eg POST/PUT) by default - see http://allseeing-i.com/ASIHTTPRequest/Changelog - my apologies to everyone who got caught by this issue. – pokeb Sep 02 '11 at 13:08
  • Thank you so much, my server side runs a Django app, on iOS i use ASIHTTPRequestVersion "v1.8-56 2011-02-06". for me this issue started after ios5. – Yogev Shelly Jan 09 '12 at 10:42
  • @Pier, I am also having the same issue. After setting ShouldAttemptPersistentConnection = NO. The frequency of this issues less. Again its occurring mainly on iOS5. – Ram Jan 12 '12 at 06:51
  • Sorry to hear @Ram but I haven't used ASIHTTPRequest in quite a while. Are you sure the problem is located in ASIHTTPRequest? Also, are you sure you aren't changing shouldAttemptPersistenConnection to YES (If you deep copy a request, that could happen). – Pier-Olivier Thibault Jan 20 '12 at 16:31
1

Secure Connection Failed

      An error occurred during a connection to login.yahoo.com.

SSL received a record with an incorrect Message Authentication Code.

(Error code: ssl_error_bad_mac_read)

The page you are trying to view can not be shown because the authenticity of the received data could not be verified. Please contact the web site owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.

krishna
  • 11
  • 1
0

On iOS 5.1, even after upgrading ASIHTTPRequest to ASIHTTPRequestVersion = @"v1.8.1-61 2011-09-19" still needed:

ASIHTTPRequest *req = [ASIHTTPRequest requestWithURL:url];
req.shouldAttemptPersistentConnection = NO;
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
pctj101
  • 141
  • 2
  • 5
0

i also had to set response setHeader Connection to "close" in by Java servlet

response.setHeader("Connection", "close");
Sameeh Harfoush
  • 610
  • 1
  • 8
  • 22