Skip to content
This repository has been archived by the owner before Nov 9, 2022. It is now read-only.
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
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 10 deletions.
@@ -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
Copy link

@digitlimit digitlimit commented on 3a75b11 Jul 10, 2015

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link

@mtpultz mtpultz commented on 3a75b11 Mar 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@ceorcham
Copy link

@ceorcham ceorcham commented on 3a75b11 Mar 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same in django...

@timallen527
Copy link

@timallen527 timallen527 commented on 3a75b11 Apr 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@salesfelipe
Copy link

@salesfelipe salesfelipe commented on 3a75b11 May 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

@gkalpak gkalpak commented on 3a75b11 May 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@mkonecny
Copy link

@mkonecny mkonecny commented on 3a75b11 May 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@salesfelipe
Copy link

@salesfelipe salesfelipe commented on 3a75b11 May 25, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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
Copy link

@jonwolski jonwolski commented on 3a75b11 Apr 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

@gkalpak gkalpak commented on 3a75b11 Apr 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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