Bug Tracker

Ticket #6230 (closed bug: fixed)

Opened 5 years ago

Last modified 3 years ago

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:
Blocking: Blocked by:

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:

  1. 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?

Change History

comment:1 Changed 4 years ago by jonespm

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: ""
                }
        });

comment:2 Changed 4 years ago by SlexAxton

  • Keywords ajax header beforesend added
  • Priority set to low
  • Status changed from new to open
  • Milestone changed from 1.4.3 to 1.5

comment:3 Changed 4 years ago by rwaldron

  • Keywords ajax,header,beforesend,ajaxrewrite added; ajax header beforesend removed

comment:4 Changed 4 years ago by jaubourg

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.

comment:5 Changed 4 years ago by jaubourg

  • Status changed from open to closed
  • Resolution set to fixed

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

Note: See TracTickets for help on using tickets.