I have a noticed a strange phenomenon in my LAMP environment.
Over the frontend I execute an AJAX post request with jQuery like this:
$.post('save.php', {data1: d1, data2: d2, [...], dataN: dN})
The variables d1
to dN
are collected from the website (e.g. from text inputs, textareas, checkboxes, etc.) with jQuery beforehand.
The file save.php
takes the post parameters data1
to dataN
and saves them in the database in one query.
The request takes about 500ms and works without problems unless I change pages (e.g. by clicking a link) during the request.
Normally, I would expect the request to be aborted and ignored (which would be fine) but (and this is the strange behaviour) the request seems to be completed but only with part of the data transmitted and thus saved.
That means for example, that the php script saves only data1
to data5
and sets data6
to dataN
to empty.
The problem seems to be caused by the AJAX request already (not the php script) since fields $_POST['data6']
to $_POST['dataN']
are not set in php in this scenario.
So my questions:
Why does this happen (is this expected behaviour)?
How can I avoid it?
Update
The problem is neither jQuery nor php solely. jQuery collects the values correctly and tries to post them to php. I just validated it - it works. The php script on the other hand handles everything it gets as expected - it just does not receive the whole request.
So the problem must be the interrupted request itself. Unlike I'd expect it does not abort or fail, it still transmits all the data until the cut off.
Then php gets this post data and starts handling it - obviously missing some information.
Update 2
I fixed the problem by adding a parameter eof
after dataN
and checking if it was set in php. This way I can be sure the whole request was transmitted.
Nevertheless this does not fix the source of the problem which I still don't understand.
Any help anyone?
Try the following actions to debug the problem:
Check post_max_size
in your php settings and compare it with the data size you are posting.
User HTTP request builder, i.e. Use Fiddler
to make an http request and check what it returns.
Use print_r($_POST);
on the top of the save.php
, to check what you are getting in it.
Use tool like Firebug
to check what jQuery
has posted.
You should also verify the json object on client side that you are posting. i.e. JSON.stringify(some_object);
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 POST
ing 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:
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.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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With