22

I’m writing a JS script that lives within a system which is now adding a custom XID header to all Ajax requests via jqXHR.setRequestHeader() in a function registered with jQuery.ajaxPrefilter().

In my script, I need to make an Ajax request to a third party site, whose Access-Control-Allow-Headers is not set up to allow this custom XID header.

It seems I have 3 options:

  1. Find a way to remove that XID header in $.ajax()’s beforeSend function, which I have confirmed gets called after the ajaxPrefilter() function.
  2. Forgo using $.ajax() entirely and just write the Ajax stuff myself.
  3. Have $.ajax() point to the system’s backend which does accept the custom XID header, and perform the request to the third party site via cURL.

Option #1 is preferred, if there’s a simple way to do it, since it will be the cleanest and fastest route. Just can’t figure out how.

I have tried overriding it like this, but it didn’t work:

beforeSend: function(jqXHR, settings) {
    jqXHR.setRequestHeader('custom-xid-header', null);
}

Any ideas?

Brandon Kelly
  • 2,033
  • 2
  • 21
  • 38
  • Pretty sure this isn't possible (unfortunately). I feel like this is easy to overcome, but would need to be changed by jQuery. The `jqXHR` is a wrapper object for a real `XMLHttpRequest`. All jQuery needs to do is keep track of any extra/custom headers (like in an `Object`), and use methods like `removeHeader` and `setHeader` to modify that Object. Then, when the real request is being created and sent, that Object will be used to *actually* add request headers to the real request. I guess depending on the real workflow/lifecycle internally, it may or may not be possible – Ian Aug 28 '13 at 15:08
  • Rats, that’s what I was afraid of. – Brandon Kelly Aug 28 '13 at 15:19
  • Yeah it looks like setting the value as `null` or `""` just sets an empty value...not remove the whole header. It might not be a bad idea to submit a feature request to jQuery. And use this as an example. Again, it may or may not be possible depending on the lifecycle internally – Ian Aug 28 '13 at 15:22
  • See complete answer at http://stackoverflow.com/questions/3372962/can-i-remove-the-x-requested-with-header-from-ajax-requests – here Jan 30 '16 at 23:28
  • Possible duplicate of [How to remove HTTP specific headers in Javascript](https://stackoverflow.com/questions/2464192/how-to-remove-http-specific-headers-in-javascript) – Liam Jun 09 '17 at 13:57

6 Answers6

6

I realize this is an old thread, but it's still a problem! Hope the following will help resolve it for someone else as it has for us.

Setting a header to null/undefined/"" after it's been set does not remove it, it sends the header still but with either no value or "undefined" or "null". This is probably never what you want, and in our case, totally screws SSO when it's the Authorization header.

The solution we came up with relies on a mix of @marlar's suggestion (thanks) and another deficiency of jQuery: You can only have ONE beforeSend() hook, and any new hook replaces the previous one. It seems that this is also true if you supply a beforeSend() in a specific $.ajax() request - it will override any default one in $.ajaxSetup(). By doing so, you prevent the default hook from setting the header. (It's not 100% ideal because there may be other things done in the default beforeSend() that will then not happen, but hey).

So this copes with both static and dynamically set headers for a specific request:

if($.ajaxSettings && $.ajaxSettings.headers) {
    delete $.ajaxSettings.headers.Authorization;
}
$.ajax({
    beforeSend: function() {}, // no op
    // ...
});

You can't do the same for prefilter(), but I think beforeSend() is the far more common way of doing this anyway.

randomsock
  • 955
  • 6
  • 9
2
$.ajaxSetup({
    beforeSend: function(jqXHR, settings) {
        jqXHR.setRequestHeader('custom-xid-header', null);
    }
})

see http://api.jquery.com/jQuery.ajaxSetup/

2

We can't delete header using beforeSend() because the data already passed to XMLHttpRequest we can only modify the headers.

But today, 2019 you can delete unwanted (non-standard) headers using jQuery.ajaxPrefilter().

$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
  delete options.headers['custom-xid-header'];
});

$.ajax({
  url: '//httpbin.org/get',
  headers: {
    'custom-xid-header': 'remove me',
    "Accept": "what/ever"
  },
  datatype: 'json',
  success: function(data) {
    console.log(data.headers);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!--script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script-->
ewwink
  • 18,382
  • 2
  • 44
  • 54
1

This worked for me:

$.ajax({
    "url": url,
    "method": "POST",
    beforeSend: function(jqXHR, settings) {
        jqXHR.setRequestHeader('x-access-token', undefined); // the header to remove
    },
    "headers": {
        "Authorization": `Bearer xxxxxxxx`,
        "Content-Type": "application/json"
    },
    "data": data,
})
0

Overiding doesn't seem's to work but there is a simple fix.

 $.ajaxSetup({
        beforeSend: function (jqXHR) {
            if (sendToken == true)
                jqXHR.setRequestHeader("Authorization", cookie);
            return true;
        }
    });

Check the sendToken variable. It's global. At the start of my app I always set it at true because I need the header set pretty much everywhere.

But when I don't want to send the "Authorization" header I just pass the global sendToken to false before any request can go. When all requests are done I just simply set it to true again...

The trick is that the jqXHR variable is local and wont keep the assigned value each time. And overiding a current value set in the ajaxSetup doesn't work because it always adds the new value instead of just replacing it. Having a condition on the top of it is I think the most simple and efficient way.

It worked for me.

Doctor
  • 7,115
  • 4
  • 37
  • 55
0

This will remove a header set with $.ajaxSetup(). I guess it will work with beforeSend() as well.

delete $.ajaxSettings.headers["custom-xid-header"]
marlar
  • 3,858
  • 6
  • 37
  • 60