What happens when no response is received for a request? I'm seeing retries

24,281

Checkout this blog post that explains what is happening: http://geek.starbean.net/?p=393

According to HTTP/1.1 RFC 8.2.4:

If an HTTP/1.1 client sends a request which includes a request body, but which does not include an Expect request-header field with the “100-continue” expectation, and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request.

Make sure you design your web app to tolerate these extra requests. And if you want the ajax request to do something only once, such as writing something to a database, then you need to design the request as idempotent. See: What is an idempotent operation?

Also, this highlights the differences between GET and POST operations: http://www.cs.tut.fi/~jkorpela/forms/methods.html

As a general design practice:
-GET operations should be designed as idempotent
-POST operations should be used for writing to databases, etc.

Share:
24,281

Related videos on Youtube

user1768233
Author by

user1768233

Updated on October 22, 2020

Comments

  • user1768233
    user1768233 over 3 years

    The question I have is probably more of a browser related question I think, but its a pretty fundamental one I'd like to find the answer too as I venture into building a web application.

    In my client side code I am doing an $.ajax call. This Post can take a while to respond. What I'm seeing is after a certain amount of time the request is being send again.

    I thought it was my $.ajax call sending it again, but no matter how many times I see the POST request on the server, I only see the beforeSend callback called once. I am fairly sure my code isn't sending it more than once, so I think its the browser retrying?

    I know my server is getting the request more then once as I ran up Wireshark and can see the post request multiple times. So my assumption is this is something to do with HTTP? I.e., if a response isn't received within a certain amount of time then the request is resent?

    Here is a sample of my call below.

    $.ajax({
                        async: false,
                        type: 'POST',
                        url: '<%= url_for('importDevice') %>',
                        data: { device: val },
                        retryLimit: 0,
                        //callback
                        success: function(data) {
                        alert('calling import');
                        if ( data == 'nomaster')
                        {
                                // Display a warning  toast, with a title
                                toastr.warning('You must set the Master Key first!', 'Warning');
                                $.ismasterset = false;
                                //reset the form contents after added
                        } else
                        {
                                $("div#content").html(data);
                        }
                        },
                         beforeSend: function(){
                        alert('in before send');
                        }
                });
    

    This is all of the relevent code, 'retryLimit' isn't being used, I just haven't removed it from my code and yes the problem was there before I put it in.

    EDITED with output from client and server.

    ok I installed 'Live Http headers for Firefox'.

    In the 'Generator' tab I see the one single call

    '#request# POST http://testhost/importdevice' 
    

    I don't see the POST in the 'headers' section though, maybe thats because there's no response?

    In my webserver though I see 2 calls about 22 seconds apart.

    [Sun Jan 13 03:08:45 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
    
    [Sun Jan 13 03:09:07 2013] [debug] POST /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
    

    I can also see these same calls in wireshark...

    This is why I was asking if this is normal behaviour to try to resend the request if a response doesn't come back, in a similar fashion to a TCP handshake and the SYN retransmission.

    NEW UPDATE

    It doesn't seem to have anything to do with my Ajax call. If I create a button with a simple HREF.

    i.e

    <a href="/importdevice?device=serverA" class="btn btn-success">TestDirect</a>
    

    Then in my 'Live HTTP headers output I get... just one instance.

    #request# GET http://172.16.118.15/importdevice?device=serverA
    

    But once again in my server logs I get.

    [Sun Jan 13 03:20:25 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS  X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
    [Sun Jan 13 03:20:48 2013] [debug] GET /importdevice (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20100101 Firefox/17.0).
    

    And in wireshark on the server I'm seeing it twice as well... and as expected my server code is called twice too... This is REALLY confusing to me.

    • T.J. Crowder
      T.J. Crowder over 11 years
      That's obviously not your real call, as it contains syntax errors. Please use copy-and-paste.
    • Alexander
      Alexander over 11 years
      What's the retryLimit property doing there? Is this all the relevant code?
    • user1768233
      user1768233 over 11 years
      ok I've cut and pasted my code exactly. this doesn't through any errors, the URL is expanded out by my web frame work. but I've tested it with the direct url and I have the same issue.
    • user1768233
      user1768233 over 11 years
      sorry 'retryLimit' isn't relavent.
  • user1768233
    user1768233 over 11 years
    Thanks Paolo, Yeah I want async off. My browser is chrome, I've also tried safari and see the same behaviour. In chrome under development tools I see the one POST with the status 'PENDING'. However in my server logs and in wireshark I see the POST request come through twice. Thanks I'll install the Live httpHeaders plugin and see if that helps
  • user1768233
    user1768233 over 11 years
    Update above. It seems its nothing to do with Ajax...now I'm really lost.
  • user1768233
    user1768233 over 11 years
    thank you! that was exactly what I was looking for..plus more!
  • Yadu
    Yadu almost 11 years
    So as per HTTP specifications, even non idempotent requests i.e. POST can be retried by the client
  • BigMacAttack
    BigMacAttack almost 11 years
    @Yadu Yes, even POST requests can be retried by the client (as experienced by the question asker). But it's not accurate to call all POST requests non-idempotent. There are occasions where one might want to design a POST request as idempotent. Be sure to read the very last section at the bottom of this page; the section entitled "Possible reasons to use "POST" for idempotent queries".
  • BoB3K
    BoB3K about 8 years
    So, this is marked as answered, which I guess it is, but no one actually says if I can do anything about it other than do a lot of work on my server side to handle duplicate requests. Is there no way to tell browsers NOT to resend POST requests or disable their timeouts--preferably from javascript/ajax?
  • Kaman Wu
    Kaman Wu about 7 years
    I have the similar problem now. Say the 1st request comes to server, the server need 3 minutes to process. After 2 minutes, the 2nd request comes in. My server will return 400 immediately. After another 1 minute, the server will return 200 (the 1st request finished). Is that correct? For now the problem is the client shows error when getting the 400 response. it will not wait for the 200 response.