Bug Tracker

Opened 12 years ago

Closed 12 years ago

Last modified 11 years ago

#8084 closed bug (wontfix)

jsonp transport overrides dataType: json setting

Reported by: anonymous Owned by: anonymous
Priority: low Milestone: 1.next
Component: ajax Version: 1.5rc1
Keywords: Cc:
Blocked by: Blocking:

Description

I upgrade my jquery lib from 1.5.b1 to 1.5.rc1. Now all my json ajax request don't work. I've got an "invalid label" error. (No problem with jquery 1.5.b1 or 1.4.4)

Change History (34)

comment:1 Changed 12 years ago by snover

Owner: set to anonymous
Status: newpending

This is not a useful bug report. Please follow the bug reporting guidelines or use the jQuery Forum for support requests.

comment:2 Changed 12 years ago by jitter

Component: unfiledajax
Priority: undecidedlow

comment:3 Changed 12 years ago by jitter

After some quick googling this blog post by Ben Nadel came up. Where he describes an issues related to evaluating json, in short doing eval( json ) and forgetting the parentheses, instead of eval( "(" + json ")" ).

From this I made the following test case which triggers this exception. (not anymore as jsfiddle now returns the correct content type). You can this test case which uses a little trick to simulate the behavior for a missing dataType statement and the server returning the wrong content type.

How can this be fixed? Either by setting dataType: "json" or by fixing the server to return the correct Content-Type for json responses, which would be application/json instead of application/javascript.

So I guess your problem has a similar cause. You propably didn't specify the dataType: "json" option on the ajax call and the server doesn't respond with the correct Content-Type header.

What's still unclear to me is how what you have done worked, in 1.4.4 and 1.5b1 but not in 1.5rc1, because afaik there wasn't a change which could have triggered this issue. The test case I gave above triggers the exception with all 3 versions of jQuery (1.4.4, 1.5b1, 1.5rc1).

Thus it would be interesting to see a test case or more information by the reporter, detailing what exactly he does to trigger this in 1.5rc1 but not in 1.4.4 or 1.5b1.


Related reading:

Last edited 12 years ago by jitter (previous) (diff)

comment:4 Changed 12 years ago by Simon

I get the same label-error.

 $.ajax({
    url : _url,
    dataType : 'json',
    ifModified : true,
    success : function (data, status, xhr) {
          console.assert(typeof data === "object");
    }
});
...

My Firebug shows me that the request is handled like dataType would be 'jsonp'. A callback is added to the url: "...?callback=jQuery1507447478875469641_1296513129436&_=1296513132903"

comment:5 in reply to:  4 Changed 12 years ago by jitter

Replying to Simon:

I get the same label-error.

 $.ajax({
    url : _url,
    dataType : 'json',
    ifModified : true,
    success : function (data, status, xhr) {
          console.assert(typeof data === "object");
    }
});
...

My Firebug shows me that the request is handled like dataType would be 'jsonp'. A callback is added to the url: "...?callback=jQuery1507447478875469641_1296513129436&_=1296513132903"

Can you provide a test case for this? What does _url look like?

comment:6 Changed 12 years ago by anonymous

Status: pendingnew

same error here with Jquery.1.5 release ... damned! I have a valid JSON data file confirmed by http://www.jsonlint.com/

comment:7 Changed 12 years ago by mechismo

I'm seeing the same issue. In my case the problem seems to be because I'm extending my ajax settings with the defaults(jQuery.ajaxSettings):

settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));

At this point the default settings have been already been modified by jQuery during init, line 6896:

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

So when I call $.getJson with my extended settings jsonp and jsonpCallback are now set which causes the check for jsonp datatype to always succeed therefore treating the call as a jsonp call... line 6909:

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		originalSettings.jsonpCallback ||
		originalSettings.jsonp != null ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				dataIsString && jsre.test( s.data ) ) ) {

In my case the quick fix was to reset the jsonp and jsonpCallback back to null:

		settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
		settings.jsonp = null;
		settings.jsonpCallback = null;

I haven't spent too much time on this so not sure exactly why this is happening but if you're seeing ajax calls treated as jsonp calls this may be the reason and the above quick fix should work.

HTH Steve

comment:8 Changed 12 years ago by anonymous

"In my case the quick fix was to reset the jsonp and jsonpCallback back to null.". Confirmed.

//  HACK:
//    jquery-1.5 sets up jsonp for all json ajax requests
//    undo the jsonp setting here so the json requests work again
jQuery.ajaxSetup({
  jsonp: null,
  jsonpCallback: null
});

jQuery(function($) {
  //  Do the rest of the application.
  $.ajax({
    url: 'data',
    dataType: 'json',
    success: function() { console.log('success') },
    error: function() { console.log('error') }
  });
});

comment:9 in reply to:  8 ; Changed 12 years ago by skywalker@…

Replying to anonymous:

"In my case the quick fix was to reset the jsonp and jsonpCallback back to null.".

In my case that works as well. Thanks!

//  HACK:
//    jquery-1.5 sets up jsonp for all json ajax requests
//    undo the jsonp setting here so the json requests work again
jQuery.ajaxSetup({
  jsonp: null,
  jsonpCallback: null
});

jQuery(function($) {
  //  Do the rest of the application.
  $.ajax({
    url: 'data',
    dataType: 'json',
    success: function() { console.log('success') },
    error: function() { console.log('error') }
  });
});

comment:10 Changed 12 years ago by snover

Status: newpending
Summary: ajax jsonjsonp transport overrides dataType: json setting

Please provide the URL that you are requesting and the URL of the page that is requesting it.

comment:11 Changed 12 years ago by scalvert

I'm seeing the same problem here. Our json is very simple:

{"estimatedCost":"0","wordCount":"137"}

comment:12 Changed 12 years ago by deckberg@…

same problem here. my quick fix was to wrap parentheses around my json and add the requesting callback on the server side. hope this is fixed in the next update

comment:13 Changed 12 years ago by anonymous

Status: pendingnew

same problem here. it was ok with jquery 1.4.2. Downloaded the 1.5 version and now appears "label error"

comment:14 in reply to:  9 Changed 12 years ago by anonymous

Replying to skywalker@…:

Replying to anonymous:

It works for me

  jQuery.ajaxSetup({ jsonp: null, jsonpCallback: null});

but I wonder if its bug or feature ;)

"In my case the quick fix was to reset the jsonp and jsonpCallback back to null.".

In my case that works as well. Thanks!

//  HACK:
//    jquery-1.5 sets up jsonp for all json ajax requests
//    undo the jsonp setting here so the json requests work again
jQuery.ajaxSetup({
  jsonp: null,
  jsonpCallback: null
});

jQuery(function($) {
  //  Do the rest of the application.
  $.ajax({
    url: 'data',
    dataType: 'json',
    success: function() { console.log('success') },
    error: function() { console.log('error') }
  });
});

comment:15 Changed 12 years ago by anonymous

what the line of the jquery.1.5.js did you added the line?

jQuery.ajaxSetup({ jsonp: null, jsonpCallback: null});

comment:16 Changed 12 years ago by jaubourg

Some information:

  • Nullifying jsonp and jsonpCallback using ajaxSetup as was suggested will break jsonp.
  • jQuery.ajaxSettings is not documented and could very well end up not being exposed anymore in future versions.
  • There are other things that will break if you extend your settings with ajaxSettings (context, contentType and all the options that are objects and that need to be deep-extended).
  • Most of the time, you don't need to manually extend your own settings object using ajaxSettings prior to calling ajax since this is already done internally by ajax in a much safer way (with all the specificities of each option handled correctly for you).
  • The rare cases where you need to have access to ajaxSettings is generally to control some custom options you set up there are defined when they're not in the settings object you wish to provide to ajax. In this situation, it's much simpler and efficient to do something like this: ( "myValue" in settings ? settings : ajaxSettings ).myValue; and it has the advantage not to break anything.
  • Sometimes you wish to use your custom options and redefine (proxy) ajax to implement some additional behavior. In that case, I'd point you to prefilters: http://api.jquery.com/extending-ajax/#Prefilters and to the custom jQuery validation I recently made which provides a good example of how you'd feature detect jQuery 1.5 and use a prefilter or fall-back to proxying ajax for older versions: https://github.com/jaubourg/jquery-validation/blob/master/jquery.validate.js#L1084

Also, make sure your ajax requests fail without any plugin installed. Some plugins will proxy ajax and do it wrong.

comment:17 Changed 12 years ago by Ben Sgroi <bsgroi@…>

I've been having the exact same problems listed above. This appears to be a bug in the most recent version of jquery validate that only manifests in 1.5. Ticket # 8064 is related: http://bugs.jquery.com/ticket/8064. I used the forked jquery.validate.js provided there and the problem went away, though using the .ajaxSetup method recommended above is less problematic.

comment:18 Changed 12 years ago by anonymous

The jquery.validate.js provided in ticket 8064 listed above works for me!!! Thanks!!!

comment:19 Changed 12 years ago by jaubourg

Resolution: wontfix
Status: newclosed

I'll close this as wontfix. Let's mark all related present and future bugs as duplicate of this one and link to http://bugs.jquery.com/ticket/8084#comment:16 so that posters get a good picture of what's happening and how to properly fix their code.

comment:20 Changed 12 years ago by anonymous

I know this ticket is Closed. But I ran into the same Issue and want to share how I got that fixed. There's only one single thing (I can see) which was Changed in how jQuery requests JSONP. The Callback name.

jQuery 1.4.x requested like

/json/?jsoncallback=jsonp15108140517397602155

with jQuery 1.5.x this was changed to

/json/?jsoncallback=jQuery15108140517397602155_1299152711383&_=1299152711448

which wasn't recognized (due to the '_' in the Callback-Name) as a valid Callback - which of course was depending heavily on my Application providing the data.

Anyone else who has this: Open your Browser and do the request by hand. Once with and once without the underscore and see what you get back. May be the Server-Side won't get that parameter as a callback as well.

comment:21 Changed 12 years ago by jaubourg

#8436 is a duplicate of this ticket.

comment:22 Changed 12 years ago by anonymous

Also seems to happen when using the ajaxQueue plugin.

comment:23 Changed 12 years ago by jaubourg

#8452 is a duplicate of this ticket.

comment:24 Changed 12 years ago by anonymous

Please explain to me (you may need to use small words) why this is not a bug.

On line 15 of /ajax/jsonp.js, ajaxPrefilter() is decorated with "json jsonp" even though the comment on line 14 clearly states that the purpose of the pre filter is to normalize JSONP requests, not JSON requests.

This pre filter adds the callback query string which causes my app to issue a 302 upon receipt. It also adds an unnecessary callback function, which interferes with the processing of my JSON request. Finally, the suggestion in comment 16 does not help me, since the pre filter is processed AFTER the pre filter in /ajax/jsonp.js, when the damage is done.

Please fix /ajax/jsonp.js by removing "json" from the pre filter.

counsellorben

comment:25 Changed 12 years ago by jaubourg

#8454 is a duplicate of this ticket.

comment:26 in reply to:  24 Changed 12 years ago by jaubourg

Replying to anonymous:

Please explain to me (you may need to use small words) why this is not a bug.

On line 15 of /ajax/jsonp.js, ajaxPrefilter() is decorated with "json jsonp" even though the comment on line 14 clearly states that the purpose of the pre filter is to normalize JSONP requests, not JSON requests.

This pre filter adds the callback query string which causes my app to issue a 302 upon receipt. It also adds an unnecessary callback function, which interferes with the processing of my JSON request. Finally, the suggestion in comment 16 does not help me, since the pre filter is processed AFTER the pre filter in /ajax/jsonp.js, when the damage is done.

Please fix /ajax/jsonp.js by removing "json" from the pre filter.

counsellorben

I suggest you actually read comment 16. Let me restate it, once again, anyway.

This behaviour (a json request being promoted as jsonp) can only occur if:

1) You provide the jsonp or jsonpCallback options or if your url contains one of the callback markers (=? or ??).

2) You use a plugin that redefines ajax and changes the options passed to the method in such a way that falls into case 1 (most of the time, by extending the options with ajaxSettings which is totally unnecessary and can even spawn nasty bugs, even in 1.4.4).

Would you be so kind as to try and remove the plugins you use then check your ajax requests. I guarantee you'll find the problem doesn't lie in 1.5 but in your application.

Yes, the prefilter is applied to jsonp AND json requests ON PURPOSE. This is actually what makes it possible to issue jsonp requests using getJSON with a url that contains one of the callback markers (=? or ??). The dataType of the request is "json", yet the prefilter has to be applied.

The only thing 1.5 changed is that the default jsonp and jsonpCallback options now sit in ajaxSettings. Those were the only two options not to be stored in this structure previously. Doing so exhibited faults into existing plugins and applications (mainly because people seem to believe it is somehow necessary to manually extend options with ajaxSettings while ajax does it internally -- and without caveats).

There's a lot of mis-conceptions in some of the presumed "solutions" to this ticket. If you actually take the time and read comment 16 carefully and stop presuming that the problem cannot possibly be on your side (because you see "json" somewhere in jQuery's code and are then convinced it's a blatant mistake while ignoring the fact jQuery has extensive unit tests regarding json requests that NEVER exhibit promotion to jsonp), then it will be a matter of seconds before you spot the problem in your application (or one of the plugins you use).

In short, stop presuming: look at your code and plugins.

Are those words numerous and small enough for you?

Last edited 12 years ago by jaubourg (previous) (diff)

comment:27 in reply to:  20 ; Changed 12 years ago by jaubourg

Replying to anonymous:

I know this ticket is Closed. But I ran into the same Issue and want to share how I got that fixed. There's only one single thing (I can see) which was Changed in how jQuery requests JSONP. The Callback name.

jQuery 1.4.x requested like

/json/?jsoncallback=jsonp15108140517397602155

with jQuery 1.5.x this was changed to

/json/?jsoncallback=jQuery15108140517397602155_1299152711383&_=1299152711448

which wasn't recognized (due to the '_' in the Callback-Name) as a valid Callback - which of course was depending heavily on my Application providing the data.

Anyone else who has this: Open your Browser and do the request by hand. Once with and once without the underscore and see what you get back. May be the Server-Side won't get that parameter as a callback as well.

What's the backend (server) you're using that won't recognize a callback name with an underscore as a valid javascript identifier?

I think it would be worth opening a new ticket for this one. If a broad server-side system has problem with underscores, it's pretty easy to have it removed (if it's a custom server-side script, that's another story).

comment:28 Changed 12 years ago by altro

I think, you must write about this hack in docs for jQuery, otherwise users will create duplicate issues (like me :-))

comment:29 in reply to:  27 Changed 12 years ago by hexa

Replying to jaubourg:

What's the backend (server) you're using that won't recognize a callback name with an underscore as a valid javascript identifier?

I'm using Slim PHP Framework and an Application I wrote for that. An that App I used a regex which didn't match '_' as a valid character in a callback. Clearly my fault since I've written that in jQuery 1.4 times where the generated callback name did contain only a-z, A-Z & 0-9. So it was fine enough to match those. Now I simply return jsonp on my App in case the parameter 'jsoncallback' is set. In this case it was NOT a jQuery issue, but resulting in the same error ("invalid label" as outlines on the very first comment here).

comment:30 Changed 12 years ago by jaubourg

#8940 is a duplicate of this ticket.

comment:31 Changed 12 years ago by anonymous

I'm doing a "retry on error" attempt on $.ajax() call. I noticed it was appending &callback=jQuery[big_number_here]_[bigger_number] to my URL. It's weird, because it's automatically changing to jsonp, while the initial request is clearly JSON only. Then, I tried rewriting the dataType inside the 'error' callback to 'text json', and it appeared to fix it? I'm not even sure how this fixes it. jsFiddle: http://jsfiddle.net/g2VJZ/11/

comment:32 in reply to:  31 Changed 12 years ago by anonymous

Replying to anonymous:

I'm doing a "retry on error" attempt on $.ajax() call. I noticed it was appending &callback=jQuery[big_number_here]_[bigger_number] to my URL. It's weird, because it's automatically changing to jsonp, while the initial request is clearly JSON only. Then, I tried rewriting the dataType inside the 'error' callback to 'text json', and it appeared to fix it? I'm not even sure how this fixes it. jsFiddle: http://jsfiddle.net/g2VJZ/11/

the correct version is http://jsfiddle.net/g2VJZ/13/

comment:33 Changed 12 years ago by anonymous

We have had these problems, but we see different behavior between the min and non-min jquery versions.

comment:34 Changed 12 years ago by gahgneh

it seems that the http://jsfiddle.net/g2VJZ/13/ works now as expected, changing to 1.6, and how this was set to wontfix and it got fixed? lol

Note: See TracTickets for help on using tickets.