Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uncomprehensible jQuery $.ajax() behavior when data contains consecutive question marks

I hope this is clear enough, I have spent a lot of time trying to pin this problem down, so I may not have much left for writing a perfect question. Besides, this might have to go into a jQuery bug report, but I'd rather post it here first as I'm a relative JavaScript novice, so maybe I did something wrong...

I created the following piece of code to reproduce it. It uses PHP to echo back the received data to the browser, although it might be able to work without any PHP.

The problem can be reproduced in Firefox 4 and Chrome 10. You'll need the console to see what's happening.

Here's the code:

<? $input = file_get_contents('php://input'); if (isset($input) and !empty($input)) {     echo $input;     die(); }  ?>  <html>     <head>         <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>         <script>             $(function(){                 var jsonData = {                     "something":"??"                 };                 jsonData = JSON.stringify(jsonData);                 var onSuccess = function(data){                     console.log("Ajax Success!");                     console.log(data);                 }                 var onError = function(jqXHR, textStatus, errorThrown){                     console.log("Ajax Error: "+textStatus);                     console.log("More info:");                     console.log(errorThrown);                                console.log(jqXHR);                          }                 console.log("Now sending this: "+jsonData+" through Ajax...");                 var ajaxCmd = {                     "url"       : "test.php",                      "dataType": "json",                     "type"  : "POST",                     "async" : false,                     "error"     : onError,                     "success"   : onSuccess,                     "data"  : jsonData                 };                 $.ajax(ajaxCmd);             });         </script>     </head>     <body>         <pre>Check your JavaScript console...</pre>     </body> </html> 

When loaded, it throws some apparently unrelated parse error or exception (depending on the browser). The json that should be sent is {"something":"??"} but if you inspect it in the network tab of Firebug (or the Chrome equivalent) you'll see that "??" is being replaced by some jQuery string which looks like: jQuery152026845051744021475_1303152126170

And that is what the server receives.

This problem only happens when there are two or more consecutive question marks in the value field inside the sent JSON object, even if there are other letters in there. With one question mark it seems to work. Also changing "dataType" to "text" fixes this. But I need all these features!

If you comment out "jsonData = JSON.stringify(jsonData);" or "$.ajax(ajaxCmd);" the errors also miraculously disappear.

More info:

Chrome console output:

test.php:21Now sending this: {"something":"??"} through Ajax... jquery.min.js:16Uncaught SyntaxError: Unexpected token : test.php:16Ajax Error: parsererror test.php:17More info: test.php:18jQuery15206220591682940722_1303153398797 was not called test.php:19 Object 

Firefox Firebug output:

Now sending this: {"something":"??"} through Ajax... Ajax Error: parsererror More info: jQuery15206494160738701454_1303153492631 was not called Object { readyState=4, responseText="{"something":"jQuery152...8701454_1303153492631"}", more...} invalid label {"something":"jQuery15206494160738701454_1303153492631"} 
like image 329
Rolf Avatar asked Apr 18 '11 19:04

Rolf


People also ask

What type property of AJAX () method specifies?

The ajax() method in jQuery is used to perform an AJAX request or asynchronous HTTP request. Parameters: The list of possible values are given below: type: It is used to specify the type of request. url: It is used to specify the URL to send the request to.

What is the use of AJAX () method?

The ajax() method is used to perform an AJAX (asynchronous HTTP) request. All jQuery AJAX methods use the ajax() method. This method is mostly used for requests where the other methods cannot be used.

How do you send AJAX request every 5 seconds?

Use just setTimeout(executeQuery, 5000); instead of setTimeout('executeQuery()', 5000); - it's shorter and faster.


2 Answers

jQuery uses ?? as a placeholder for the callback function when using jsonp. When it parses an Ajax request, and it finds the double questionmark (or more questionmarks), it automatically assumes that you are trying to use jsonp. When you set the content-type manually, it will ignore the questionmarks.

So, avoid the problem by using contentType:

$.ajax(     url: "your-url.php",     dataType: "json",                 // what you expect the server to return     contentType: "application/json",  // what you are sending     ... ); 

For reference:

jQuery Bugtracker: $.AJAX CHANGED THE POST CONTENT IF INCLUDE "??" (2 QUESTION MARK)

Hopes it saves someone else from hours of debugging...

like image 174
Justus Romijn Avatar answered Oct 14 '22 22:10

Justus Romijn


If you're not going to format the "data" value as a valid HTML query string, you shouldn't pre-stringify it. As you noted, if you don't call "JSON.stringify()" then it works. That's because the library already knows to handle that for you.

Now, if you want to send your JSON string as a parameter itself to server side code that expects to decode some JSON, then you need to set it up as a parameter:

    $.ajax(url, {       // ...       data: { jsonParam: jsonData },       // ...     }); 

Now your server will see an HTTP request with a parameter called "jsonParam", and its value will be your JSON-stringified string.

like image 32
Pointy Avatar answered Oct 14 '22 23:10

Pointy