Skip to content
Permalink
Browse files

fix($http): remove 'X-Requested-With' from header defaults

X-Requested-With header is rarely used in practice and by using
it all the time we are triggering preflight checks for crossdomain
requests.

We could try detecting if we are doing CORS requests or not, but
it doesn't look like it's worth the trouble.

BREAKING CHANGE: X-Requested-With header is not set by $http service
any more. If anyone actually uses this header it's quite easy to add
it back via:

```
myAppModule.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}]);
```

Closes #1004
  • Loading branch information
rkirov authored and IgorMinar committed Nov 26, 2012
1 parent a32bc40 commit 3a75b1124d062f64093a90b26630938558909e8d
Showing with 3 additions and 10 deletions.
  1. +1 −3 src/ng/http.js
  2. +2 −7 test/ng/httpSpec.js
@@ -108,8 +108,7 @@ function $HttpProvider() {
// default headers
headers: {
common: {
'Accept': 'application/json, text/plain, */*',
'X-Requested-With': 'XMLHttpRequest'
'Accept': 'application/json, text/plain, */*'
},
post: {'Content-Type': 'application/json;charset=utf-8'},
put: {'Content-Type': 'application/json;charset=utf-8'}
@@ -212,7 +211,6 @@ function $HttpProvider() {
*
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
* - `Accept: application/json, text/plain, * / *`
* - `X-Requested-With: XMLHttpRequest`
* - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)
* - `Content-Type: application/json`
* - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)
@@ -377,8 +377,7 @@ describe('$http', function() {

it('should set default headers for GET request', function() {
$httpBackend.expect('GET', '/url', undefined, function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest';
return headers['Accept'] == 'application/json, text/plain, */*';
}).respond('');

$http({url: '/url', method: 'GET', headers: {}});
@@ -389,7 +388,6 @@ describe('$http', function() {
it('should set default headers for POST request', function() {
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'application/json;charset=utf-8';
}).respond('');

@@ -401,7 +399,6 @@ describe('$http', function() {
it('should set default headers for PUT request', function() {
$httpBackend.expect('PUT', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'application/json;charset=utf-8';
}).respond('');

@@ -412,8 +409,7 @@ describe('$http', function() {

it('should set default headers for custom HTTP method', function() {
$httpBackend.expect('FOO', '/url', undefined, function(headers) {
return headers['Accept'] == 'application/json, text/plain, */*' &&
headers['X-Requested-With'] == 'XMLHttpRequest';
return headers['Accept'] == 'application/json, text/plain, */*';
}).respond('');

$http({url: '/url', method: 'FOO', headers: {}});
@@ -424,7 +420,6 @@ describe('$http', function() {
it('should override default headers with custom', function() {
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
return headers['Accept'] == 'Rewritten' &&
headers['X-Requested-With'] == 'XMLHttpRequest' &&
headers['Content-Type'] == 'Rewritten';
}).respond('');

10 comments on commit 3a75b11

@digitlimit

This comment has been minimized.

Copy link

@digitlimit digitlimit replied Jul 10, 2015

Laravel / Symphony actually depend on this feature to dictate AJAX requests.

 /**
 * Returns true if the request is a XMLHttpRequest.
 *
 * It works if your JavaScript library sets an X-Requested-With HTTP header.
 * It is known to work with common JavaScript frameworks:
 *
 * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript
 *
 * @return bool true if the request is an XMLHttpRequest, false otherwise
 *
 * @api
 */
public function isXmlHttpRequest()
{
    return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}
@mtpultz

This comment has been minimized.

Copy link

@mtpultz mtpultz replied Mar 3, 2016

Yep, and still do 3 years later apparently. This took a bit to track down.

@ceorcham

This comment has been minimized.

Copy link

@ceorcham ceorcham replied Mar 17, 2016

The same in django...

@timallen527

This comment has been minimized.

Copy link

@timallen527 timallen527 replied Apr 27, 2016

The .NET MVC IsAjaxRequest still depends on this header as well.

@salesfelipe

This comment has been minimized.

Copy link

@salesfelipe salesfelipe replied May 24, 2016

Guys, changing the client side is not the answer. Instead you should change how your server handles the CORS request. If you are using Nodejs on your server, you can try this:

// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "
");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});

For more info, check this out:

https://github.com/ccoenraets/directory-ionic-nodejs/blob/master/server.js

@gkalpak

This comment has been minimized.

Copy link
Member

@gkalpak gkalpak replied May 25, 2016

In case anyone missed it, you can add it to all $http requests using $httpProvider#defaults.

@mkonecny

This comment has been minimized.

Copy link

@mkonecny mkonecny replied May 25, 2016

@felippeSales changing the server side is definitely not the answer.

@salesfelipe

This comment has been minimized.

Copy link

@salesfelipe salesfelipe replied May 25, 2016

@mkonecny Actually, it was. I'm building an app using MEAN stack on heroku and Ionic on client side. Thats how I finally fixed it: https://github.com/expressjs/cors/blob/master/README.md

@jonwolski

This comment has been minimized.

Copy link

@jonwolski jonwolski replied Apr 11, 2017

Old issue, but for posterity's sake:

The presence of this custom header had protected against CSRF. This detrimental change event got a mention on OWASP: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Protecting_REST_Services:_Use_of_Custom_Request_Headers

@gkalpak

This comment has been minimized.

Copy link
Member

@gkalpak gkalpak replied Apr 11, 2017

@jonwolski, also note that $http uses a different header, X-XSRF-HEADER (the name of the header is configurable), specifically for protecting against CSRF vulnerabilities.

Please sign in to comment.
You can’t perform that action at this time.