I have a browser-based client that makes AJAX calls to a PHP/Apache back-end. When a button is clicked, the client loops through a list of "providers" and sends an Ajax request to each of them with exactly the same payload.
Randomly some of the requests in the loop are arriving at the server side with a blank POST body. What is really strange about this is the fact that other requests in the same loop are arriving properly populated. Sometimes we are seeing all of the items in the loop arriving with a blank body, sometimes some in the loop. It is really strange!
Environment details:
Client = JQuery 3.3.1, JQueryUI 1.12.1, Bootstrap 3.3.7, JQuery validate 1.19.0
Server = Apache 2.4, PHP 7.1
We cannot actually reproduce the problem in a development environment, but logging in production is clearly showing that this is happening regularly on a daily basis (maybe 5% of requests). We have deployed monitoring on the client browsers to trap any errors and there is nothing in terms of exceptions or anything that looks like it could be related.
The sample below shows what we are doing on the client side.
1) bind a click event to
2) when clicked, populate a request object
3) loop through the list of "providers", posting request from 2 to PHP server
$(document).ready(function() {
bindEvents();
}
function bindEvents() {
$("#myButton").click(function(event) {
event.preventDefault();
handleClick();
});
}
function handleClick() {
var request = ...;
...
var save=false;
if (....) {
save=true;
}
var providers = ["provider1", "provider2", "provider3", "provider4", "provider5", "provider6"];
var ndx;
for (ndx=0; ndx<providers.length; ++ndx) {
doRequestSend("action/"+(save?"save":"verify"), request, providers[ndx]);
}
}
function doRequestSend(action, request, provider) {
request['apiKey']=getAPIKey();
var url=baseURL+"/api/"+provider+"/"+action;
$.ajax({
type: "POST",
url: url,
data: JSON.stringify(request),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data){
...
},
failure: function(errMsg) {
...
},
error : function(jqXHR, textStatus, errorThrown) {
...
}
});
}
Obviously, it is difficult to figure out the issue when I cannot reproduce. However, am hoping the someone might spot a problem with the approach that could be resulting in the issue.
Alternatively, open to any random/crazy ideas that could explain HOW this could possibly be happening! Some requests in the loop arrive fine, others arrive blank!
Notes:
- Although the loop POST to a slightly different url with each iteration, on the server side, they all end up at the same entry point and the first thing that is done is a log of the body (this is how we know it is blank!)
- The only browsers that (to date) seem to have experienced the issue are Chrome 73 & 74 on Windows. This might not be relevant!
Anyone got any ideas or things to try that might track down the source?
Cheers!
Related
I recently perform some ajax request on my website but I'm still beginner.
Here is a stupid question: How to send (POST) a data to the server without waiting any response ?
In all the example I found on internet, the ajax call is used to reload a part of the page. It work perfectly, but my idea here is just to send a data that could be store in DB for example without waiting any response.
I'm using Zend framework with MVC pattern. I tried something like:
$.ajax({
type: "POST",
url:'/controller/action',
data: { myDataToPost: aData },
success:function(response){
},
failure:function(){
alert('Could not save your entry');
}
});
It works fine if I define an action in my controller but I can see in firebug an 404 error on controller/action page. For sure it doesn't exist because i don't want any response...
Many thanks for your help!
Cedric.
"Here is a stupid question: How to send (POST) a data to the server without waiting any response ?"
$.ajax({
timeout: 1
});
Set the request timeout to 1 millisecond (zero doesn't work), thus giving the xmlHttpRequest 1 millisecond to complete (go to server, process request, return response, which is virtually impossible), otherwise mark it as timed out (failed).
I'm making a AJAX request like this:
$("#botao_pesquisar_material").click(function(){
$(this).attr("disabled", "disabled");
$("#material").addClass('loading');
$.ajax({
url: '{{ URL::base() }}/material/lista_ajax/',
dataType: 'json',
cache: false,
error: function(data)
{
console.log(data);
},
success: function(data) {
for(x in data)
{
console.log(data[x]);
}
}
});
My PHP method is ok because when I access it via URL, it returns me the expected JSON and when I call this on localhost, it works perfectly so it isn't about special characters or something else with the data.
When I run this on my server I have this:
GET http://dc.portaldeideias.com.br:8080/sergios/public/material/lista_ajax/?callback=jQuery172007718208665028214_1342725644520&_=1342725649090 500 (Internal Server Error) jquery.js:4
f.support.ajax.f.ajaxTransport.send jquery.js:4
f.extend.ajax jquery.js:4
$.click.$.ajax.url
f.event.dispatch jquery.js:3
f.event.add.h.handle.i
Using console.log(data) I have the entire JSON response but here is what is really strange:
The readyState is 4
The responseText is [{"attributes":{"pk_a030_id":78,"a030_descricao":"Camur\u00e7a"},"original":{"pk_a030_id":78,"a030_descricao":"Camur\u00e7a"},"relationships":[],"exists":true,"includes":[]}]
The statusText is Internal Server Error
So, the requested value is created but I receive a Internal Server Error
Sorry for posting this as an answer, but I don't have the required privileges to add this as a comment for your question.
Have you noticed that the URL in the javascript log http://localhost:8080/sergios/public/material/lista_ajax/ is different than the one provided in your screenshot http://dc.p[...]s.com.br:8080/sergios/public/material/lista_ajax?
Could it be the case that you have two different versions of the lista_ajax PHP method hosted in two different servers (maybe one remote and the other one local), and that's why it works flawless when seeing it from the browser and has bugs when tested with ajax?
It's also important to notice that if you are browsing a website hosted on a remote server, and the ajax is configured to a localhost address, it will do a request for your own machine, not the remote server (javascript runs in the browser, so localhost translates to its own client address).
Maybe this is not the case, but it was worth commenting.
I have made a simple chat application which uses long-polling approach using jquery,
function sendchat(){
// this code sends the message
$.ajax({
url: "send.php",
async: true,
data: { /* send inputbox1.value */ },
success: function(data) { }
});
}
function listen_for_message(){
// this code listens for message
$.ajax({
url: "listen.php",
async: true,
timeout:5000,
success: function(data) { // the message recievend so display that message and make new request for listening new messages
$('#display').html(data);
listen_for_message();
}
});
}
THIS SHOULD HAPPEN : after page loaded the infinite request for listen.php occurs and when user sends message, the code sends message to database via send.php.
PROBLEM is, using firebug i've found that send.php request which is performed after listen.php request, is remains pending. means the request for send message is remains pending.
The issue was because of session locking;
both send.php and listen.php files use session variables,
so session is locked in listen.php file and the other file (here send.php file) can't be served after the session frees from serving another file ( here listen.php).
How do I implement basic "Long Polling"?
the link above is a similar question that may help you.
it does not have to be on a database, it can be saved on a tmp file, but your problem is that you are choking the browser by performing too many requests, any one browser handles two requests at a time, which means you should really allow the browser to finish the first requests first then do the second one... and so on...
you do not need to do send.php and listen.php, because you can do it simply on one page both of them.
function check(){
$.ajax({
url : 'process.php',
data : {msg:'blabla'/* add data here to post e.g inputbox1.value or serialised data */}
type : 'post',
success: function (r){
if(r.message){
$('#result').append(r.message);
check();//can use a setTimeout here if you wish
}
}
});
}
process.php
<?php
$msg = $_POST['msg'];//is blabla in this case.
$arg['message'] = $msg;//or grab from db or file
//obviously you will have to put it on a database or on a file ... your choice
//so you can differentiate who sent what to whom.
echo json_encode($arg);
?>
obviously this are only guide lines, but you will exhaust your bandwidth with this method, however it will be alot better because you have only one small file that returns either 0 to 1 byte of information, or more if there is a message posted.
I have not tested this so don't rely on it to work straight away you need a bit of changes to make it work but just helps you understand how you should do it.
however if you are looking for long pulling ajax there are loads of scripts out there already made and fine tuned and have been test, bug fixed and many minds help built it, my advice is don't re-invent the wheel
I have here a test page that should do a jQuery JSONP cross-domain request not once, but twice:
http://www.starcitygames.com/json_test.php
And it should query this here page here to pull up some test data:
http://scg.im/ajax/fetch_recent_URLs.php?callback=fred
After bashing my head against the wall for an entire morning where I got absolutely zero response from this script, pro or con, I put a mail() call in the fetch_recent_URLs script to mail me whenever the remote page was loaded.
It turns out that despite several loadings, tweakings, etc. of the script, it never actually calls the scg.im page. The script isn't broken, returns no fatal errors in JavaScript, et cetera - it just doesn't actually ever seem to fire the AJAX call.
Even more perplexingly, regular JSON calls (to this domain) work fine.
The script(s) are as such:
$.ajax({
url: "http://scg.im/ajax/fetch_recent_URLs.php",
type: "GET",
dataType: "jsonp",
error: function(xhr, status, error) {
alert("error");
},
success: function(json) {
alert("success");
}
});
$.getJSON("http://scg.im/ajax/fetch_recent_URLs.php?callback=?", function(rtndata) {
alert("Returned!");
});
Both are taken from various test pages that claims this works. I've also tried it in jQuery 1.6, changed the header, etc., all encountering the same problem; no matter what I do, jQuery never actually calls the page. (Again, I know this because the script mails me every time it's loaded, and it doesn't email me at all when I load this page.)
Any idea why this is not working? I'm doing, as far as I can tell, everything according to plan (and about five variations on these scripts to boot).
Edit: SOLVED! I figured it out, and it's entirely stupid.
If you have NoScript enabled for FireFox (and you arguably should), AND you have not allowed scripts from the new domain (in this case, scg.im), then NoScript will prevent the domain request before it even begins. Good security. Thoroughly baffling.
I can't for the life of me figure out why this is happening.
This is kind of a repost, so forgive me, but I have new data.
I am running a javascript log out function called logOut() that has make a jQuery ajax call to a php script...
function logOut(){
var data = new Object;
data.log_out = true;
$.ajax({
type: 'POST',
url: 'http://www.mydomain.com/functions.php',
data: data,
success: function() {
alert('done');
}
});
}
the php function it calls is here:
if(isset($_POST['log_out'])){
$query = "INSERT INTO `token_manager` (`ip_address`) VALUES('logOutSuccess')";
$connection->runQuery($query); // <-- my own database class...
// omitted code that clears session etc...
die();
}
Now, 18 hours out of the day this works, but for some reason, every once in a while, the POST data will not trigger my query. (this will last about an hour or so).
I figured out the post data is not being set by adding this at the end of my script...
$query = "INSERT INTO `token_manager` (`ip_address`) VALUES('POST FAIL')";
$connection->runQuery($query);
So, now I know for certain my log out function is being skipped because in my database is the following data:
alt text http://img535.imageshack.us/img535/2025/screenshot20100519at125h.png
if it were NOT being skipped, my data would show up like this:
alt text http://img25.imageshack.us/img25/8104/screenshot20100519at125.png
I know it is being skipped for two reasons, one the die() at the end of my first function, and two, if it were a success a "logOutSuccess" would be registered in the table.
Any thoughts? One friend says it's a janky hosting company (hostgator.com). I personally like them because they are cheap and I'm a fan of cpanel. But, if that's the case???
Thanks in advance.
-J
Ok, for those interested.
I removed the full URL http://www.mydomain.com/functions.php
and replaced it with the local path functions.php and that did the trick.
Apparently AJAX has issues with cross domain ajax calls and I'm not on a dedicated server, so I imagine what's happening is every couple hours (or minutes) I am somehow hitting my script from a different location causing AJAX to dismiss the POST data.
-J
Try enabling error reporting on the jquery $.ajax function, your code would look something like
function logOut(){
var data = new Object;
data.log_out = true;
$.ajax({
type: 'POST',
url: 'http://www.mydomain.com/functions.php',
data: data,
success: function() {
alert('done');
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus+" - "+errorThrown);
}
});
}
See if that sheds light on your situation.
I have a strong feeling that it's more of a server side issue rather than the client's.
The odd thing is that you see the problem for a period of time. If the client works at all, then at the minimum refreshing the page or restarting the browser should fix it.
The die() at the end of the function is suspicious, but I am not quite sure how it will affect it.
Btw you can see http headers in FireBug's Net tab, to know whether those parameters has been sent properly.