jQuery post request interrupted: Only half of post parameters arrive jQuery post request interrupted: Only half of post parameters arrive ajax ajax

jQuery post request interrupted: Only half of post parameters arrive


Try the following actions to debug the problem:

  1. Check post_max_size in your php settings and compare it with the data size you are posting.

  2. User HTTP request builder, i.e. Use Fiddler to make an http request and check what it returns.

  3. Use print_r($_POST); on the top of the save.php, to check what you are getting in it.

  4. Use tool like Firebug to check what jQuery has posted.

  5. You should also verify the json object on client side that you are posting. i.e. JSON.stringify(some_object);

  6. Try posting some basic sample data { "data1":1, "data2":2, "data3":3, "data4":4, "data5":5 , "data6":6 }

Most probably you are sending to much data or likely data is invalid!

Edits:Very Foolish act but lets say you posted count as well. so directly check isset($_POST['data'.$_POST['count']] )


I think we can rule out problems at the server site (unless it's some exotic or self-crafted server daemon), because nobody ever sends "end-of-data"-parameters with a HTTP POST request to make sure all data is really sent. This is handled by HTTP itself (see e.g. Detect end of HTTP request body). Moreover, I don't think that you have to check the Content-Length header when POSTing data to your server, simply because of the fact that nobody does this, ever. At least not in totally common circumstances like you describe them (sending Ajax POST through jQuery).

So I suppose that jQuery sends a syntactically correct POST, but it's cut off. My guess is that if you interrupt this data collecting by navigating to another page, jQuery builds an Ajax request out of the data which it was able to gather and sends a syntactically correct POST to your server, but with cut off data.

Since you're using Firebug, please go to its net tab and activate persist, so traffic data is not lost when navigating to another page. Then trigger your Ajax POST, navigate to another page (and thereby "interrupt" the Ajax call) and check in Firebug's net tab what data has actually been sent to the server by opening ALL the POST requests and checking the Headers tab (and inside this, the Request Headers tab).

My guess is that one of two things might happen:

  1. You will see that the data sent to the server is cut off already in the headers being presented to you in Firebug's net tab and the Content-Length is calculated correctly according to the actual (cut off) length of the POST data. Otherwise, I'm sure the server would reject the request as Bad Request as a whole.
  2. You will see that there are multiple POST requests, some of them (perhaps with the full, non-cut off data) actually interrupted and therefore never reaching the server, but at least one POST request (again, with the cut off data) that ist triggered by some other mechanism in your Javascript, i.e. not the trigger you thought, but by navigating to another page, more and other Ajax requests might be triggered (just a guess since I don't know your source code).

In either case, I think you'll find out that this problem ist client related and the server just processes the (incomplete, but (in terms of HTTP) syntactically valid) data the client sent to it.

From that point on, you could debug your Javascript and implement some mechanism that prevents sending incomplete data to your server. Again, it's hard to tell what to do exactly since I don't know the rest of your source code, but maybe there's some heavy action going on in collecting the data, and you could possibly make sure that the POST only happens if all the data is really collected. Or, perhaps you could prevent navigation until the Ajax request is completed or such things.

What might be interesting, if all of this doesn't make sense, would be to have a look at more of your source code, especially how the Ajax POST is triggered and if there are any other events and such if you navigate to another page. Sample data you're sending could also be interesting.

EDIT: I'd also like to point out that outputting data with console.log() might be misleading, since it's in no way guaranteed that this is the data actually being sent, it's just a logline which evaluates to the given output at the exact time when console.log() is called. That's why I suggested sniffing the network traffic, because then (and only then) you can be sure what is really being sent (and received).Nonetheless, this is a little tricky if you're not used to it (and impossible if you use encrypted traffic e.g. by using HTTPS), so the Firebug net tab might be a good compromise.


You can verify the value of the Content-Length header being received by the PHP.

This value ought to have been calculated client side when running the POST query. If it does not match, that's your error then and there. And that's all the diagnostics you need - if the Content-Length does not match the POST data, reject the POST as invalid; no need of extra parameters (computing the POST data length might be a hassle, though). Also, you might want to investigate why does PHP, while decoding the POST and therefore being able to verify its length, nonetheless seems to accept a wrong length (maybe the information needed to detect the error is somewhere among the $_SERVER variables?).

If it does match though, and still data isn't arriving (i.e., the Content-Length is smaller, and correctly describes the cut-off POST), then it is proof that the POST was inspected after the cut-off, and therefore either the error is in the browser (or, unlikely, in jQuery) or there is something between the browser and the server (a proxy?) that is receiving an incomplete query (with Content-Length > Actual length) and is incorrectly rewriting it, making it appear "correct" to the server, instead of rejecting it out of hand.

Some testing of both the theory and the workaround

Executive summary: I got the former wrong, but the latter apparently right. See code below for a sample that works on my test system (Linux OpenSuSE 12.3, Apache).

I believed that a request with wrong Content-Length would be refused with a 400 Bad Request. I was wrong. It seems that at least my Apache is much more lenient.

I used this simple PHP code to access the key variables of interest to me

<?php    $f = file_get_contents("php://input");    print $_SERVER['CONTENT_LENGTH'];    print "\nLen: " . strlen($f) . "\n";?>

and then I prepared a request with a wrong Content-Length sending it out using nc:

POST /p.php HTTP/1.0Host: localhostContent-Length: 666answer=42

...and lo and behold, nc localhost 80 < request yields no 400 error:

HTTP/1.1 200 OKDate: Fri, 14 Jun 2013 20:56:07 GMTServer: Apache/2.2.22 (Linux/SUSE)X-Powered-By: PHP/5.3.17Vary: Accept-EncodingContent-Length: 12Content-Type: text/html666Len: 10

It occurred to me then that content length might well be off by one or two in case the request ended with carriage return, and what carriage return - LF? CRLF?. However, when I added simple HTML to be able to POST it from a browser

<form method="post" action="?"><input type="text" name="key" /><input type="submit" value="go" /></form>

I was able to verify that in Firefox (latest), IE8, Chrome (latest), all running on XP Pro SP3, the value of the Content-Length is the same as the strlen of php://input.

Except when the request is cut off, that is.

The only problem is that php://input is not always available even for POST data.

This leaves us still in a quandary:

IF THE ERROR IS AT THE NETWORK LEVEL, i.e., the POST is prepared and supplied with a correct Content-Length, but the interruption makes it so that the whole data is cut off as this comment by Horen seems to indicate:

So only the first couple of post parameters arrived, sometimes the value of one parameter was even interrupted in the middle

then really checking Content-Length will prevent PHP from handling an incomplete request:

<?php    if ('POST' == $_SERVER['SERVER_PROTOCOL'])    {            if (!isset($_SERVER['Content-Length']))            {                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', True, 400);                die();            }            if (strlen(file_get_contents('php://input'))!=(int)($_SERVER['Content-Length']))            {                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', True, 400);                die();            }    }    // ... go on?>

ON THE OTHER HAND if the problem is in jQuery, i.e. somehow the interruption prevents jQuery from assembling the full POST, and yet the POST is made up, the Content-Length calculated of the incomplete data, and the packet sent off -- then my workaround can't possibly work, and the "telltale" extra field must be used, or... perhaps the .post function in jQuery might be extended to include a CRC field?