Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 53359d5

Browse files
caiotoonpetebacondarwin
authored andcommitted
fix($http): ensure case-insens. header overriding
If user send content-type header, both content-type and default Content-Type headers were sent. Now default header overriding is case-insensitive.
1 parent f1b94b4 commit 53359d5

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

src/ng/http.js

+30-7
Original file line numberDiff line numberDiff line change
@@ -649,17 +649,12 @@ function $HttpProvider() {
649649
transformRequest: defaults.transformRequest,
650650
transformResponse: defaults.transformResponse
651651
};
652-
var headers = {};
652+
var headers = mergeHeaders(requestConfig);
653653

654654
extend(config, requestConfig);
655655
config.headers = headers;
656656
config.method = uppercase(config.method);
657657

658-
extend(headers,
659-
defaults.headers.common,
660-
defaults.headers[lowercase(config.method)],
661-
requestConfig.headers);
662-
663658
var xsrfValue = isSameDomain(config.url, $browser.url())
664659
? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
665660
: undefined;
@@ -673,7 +668,11 @@ function $HttpProvider() {
673668

674669
// strip content-type if data is undefined
675670
if (isUndefined(config.data)) {
676-
delete headers['Content-Type'];
671+
forEach(headers, function(value, header) {
672+
if (lowercase(header) === 'content-type') {
673+
delete headers[header];
674+
}
675+
});
677676
}
678677

679678
if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
@@ -729,6 +728,30 @@ function $HttpProvider() {
729728
? resp
730729
: $q.reject(resp);
731730
}
731+
732+
function mergeHeaders(config) {
733+
var defHeaders = defaults.headers,
734+
reqHeaders = extend({}, config.headers),
735+
defHeaderName, lowercaseDefHeaderName, reqHeaderName;
736+
737+
defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
738+
739+
// using for-in instead of forEach to avoid unecessary iteration after header has been found
740+
defaultHeadersIteration:
741+
for (defHeaderName in defHeaders) {
742+
lowercaseDefHeaderName = lowercase(defHeaderName);
743+
744+
for (reqHeaderName in reqHeaders) {
745+
if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
746+
continue defaultHeadersIteration;
747+
}
748+
}
749+
750+
reqHeaders[defHeaderName] = defHeaders[defHeaderName];
751+
}
752+
753+
return reqHeaders;
754+
}
732755
}
733756

734757
$http.pendingRequests = [];

test/ng/httpSpec.js

+20
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,21 @@ describe('$http', function() {
717717
$httpBackend.flush();
718718
});
719719

720+
it('should override default headers with custom in a case insensitive manner', function() {
721+
$httpBackend.expect('POST', '/url', 'messageBody', function(headers) {
722+
return headers['accept'] == 'Rewritten' &&
723+
headers['content-type'] == 'Content-Type Rewritten' &&
724+
headers['Accept'] === undefined &&
725+
headers['Content-Type'] === undefined;
726+
}).respond('');
727+
728+
$http({url: '/url', method: 'POST', data: 'messageBody', headers: {
729+
'accept': 'Rewritten',
730+
'content-type': 'Content-Type Rewritten'
731+
}});
732+
$httpBackend.flush();
733+
});
734+
720735
it('should not set XSRF cookie for cross-domain requests', inject(function($browser) {
721736
$browser.cookies('XSRF-TOKEN', 'secret');
722737
$browser.url('http://host.com/base');
@@ -734,7 +749,12 @@ describe('$http', function() {
734749
return !headers.hasOwnProperty('Content-Type');
735750
}).respond('');
736751

752+
$httpBackend.expect('POST', '/url2', undefined, function(headers) {
753+
return !headers.hasOwnProperty('content-type');
754+
}).respond('');
755+
737756
$http({url: '/url', method: 'POST'});
757+
$http({url: '/url2', method: 'POST', headers: {'content-type': 'Rewritten'}});
738758
$httpBackend.flush();
739759
});
740760

0 commit comments

Comments
 (0)