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 Oct 12, 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
View
@@ -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)
View
@@ -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.

Show comment
Hide comment
@digitlimit

digitlimit 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');
}

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.

Show comment
Hide comment
@mtpultz

mtpultz Mar 3, 2016

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

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.

Show comment
Hide comment
@ceorcham

ceorcham Mar 17, 2016

The same in django...

ceorcham replied Mar 17, 2016

The same in django...

@timallen527

This comment has been minimized.

Show comment
Hide comment
@timallen527

timallen527 Apr 27, 2016

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

timallen527 replied Apr 27, 2016

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

@salesfelipe

This comment has been minimized.

Show comment
Hide comment
@salesfelipe

salesfelipe 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

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.

Show comment
Hide comment
@gkalpak

gkalpak May 25, 2016

Member

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

Member

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.

Show comment
Hide comment
@mkonecny

mkonecny May 25, 2016

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

mkonecny replied May 25, 2016

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

@salesfelipe

This comment has been minimized.

Show comment
Hide comment
@salesfelipe

salesfelipe 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

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.

Show comment
Hide comment
@jonwolski

jonwolski 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

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.

Show comment
Hide comment
@gkalpak

gkalpak Apr 11, 2017

Member

@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.

Member

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.