Skip to main content

Bug Tracker

Side navigation

#6230 closed bug (fixed)

Opened March 05, 2010 09:09AM UTC

Closed January 11, 2011 10:01PM UTC

Last modified March 14, 2012 01:57AM UTC

WEBKIT: xhr.setRequestHeader("Accept", ...) *appends* the value instead of replacing it

Reported by: jpzwarte Owned by:
Priority: low Milestone: 1.5
Component: ajax Version: 1.4.2
Keywords: ajax,header,beforesend,ajaxrewrite Cc:
Blocked by: Blocking:
Description

dataType: 'html',

beforeSend: function(xhr) {

xhr.setRequestHeader("Accept", "text/javascript, */*");

}

I have the above options in my $.ajax call to a Rails application. The html dataType is to prevent errors from jQuery trying to parse the response as script (which it isn't, it's html). The beforeSend callback is to get Rails to see the request as an AJAX request (respond_to handler in rails).

This works fine in Firefox: the "Accept" request header is set to the above value. In Webkit however (tested in Safari 4.0.4 and Webkit nightly) it appends the above value to the already existing value set by jQuery itself ("text/html, */*" based on the dataType). The end result being an Accept value of: "text/html, */*, text/javascript, */*" . This causes Rails to see the request as a normal, non-ajax request, triggering the wrong response.

I checked the Prototype source and it seems to prevent the Webkit behavior from becoming an issue by having the "Accept" header as an option in the ajax call. See http://api.prototypejs.org/ajax_section.html (the requestHeaders common option).

It seems that the W3C spec on XmlHttpRequest is vague. http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method states:

7. If header is in the author request headers list either use multiple headers, *combine the values* or use a combination of those (section 4.2, RFC 2616). [RFC2616]

Emphasis added by me.

Could be that Webkit does the right thing and that Firefox is wrong, or the other way around. Can we adopt the same behavior in jQuery (requestHeaders option) as in Prototype to workaround the different browser behaviors?

Attachments (0)
Change History (5)

Changed September 27, 2010 08:29PM UTC by jonespm comment:1

I think the bigger problem is there is no way to override the defaults that are appended, even though there *are* ways to override these without using the beforeSend. This is because "*/*" is always appended to the setRequestHeader. I'd suggest changing it to append a default rather than a hardcoded value.

@@ -5139,7 +5139,7 @@
 
                        // Set the Accepts header for the server, depending on the dataType
                        xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
-                               s.accepts[ s.dataType ] + ", */*" :
+                               s.accepts[ s.dataType ] + "," + s._default :
                                s.accepts._default );
                } catch(e) {}

Then you can at least override it in $.ajaxSetup with a new "accepts"

        $.ajaxSetup ({
                accepts: {
                        xml: "application/xml, text/xml",
                        html: "text/html",
                        script: "text/javascript, application/javascript",
                        json: "application/json, text/javascript",
                        text: "text/plain",
                        // Hack for Chrome/Safari
                        _default: ""
                }
        });

Changed October 23, 2010 11:46PM UTC by SlexAxton comment:2

keywords: → ajax header beforesend
milestone: 1.4.31.5
priority: → low
status: newopen

Changed December 27, 2010 10:37PM UTC by rwaldron comment:3

keywords: ajax header beforesendajax,header,beforesend,ajaxrewrite

Changed January 09, 2011 06:00AM UTC by jaubourg comment:4

Could this be checked against the code in the repository? Headers are put in a temporary map before being set on the native xhr object now so I'm pretty confident this is fixed.

Changed January 11, 2011 10:01PM UTC by jaubourg comment:5

resolution: → fixed
status: openclosed

Fixes #6230. Added a unit test to control that, since the ajax rewrite, setting the Accept header actually replaced the previous value and didn't append to it (tested in Safari 4.0.4 for which the problem was specifically reported).

Changeset: 6504d4f7005c99ea4064068f3d712322a064b97a