diff options
| -rw-r--r-- | src/ng/http.js | 37 | ||||
| -rw-r--r-- | test/ng/httpSpec.js | 20 | 
2 files changed, 50 insertions, 7 deletions
diff --git a/src/ng/http.js b/src/ng/http.js index fbdc89a5..2b9c7475 100644 --- a/src/ng/http.js +++ b/src/ng/http.js @@ -649,17 +649,12 @@ function $HttpProvider() {          transformRequest: defaults.transformRequest,          transformResponse: defaults.transformResponse        }; -      var headers = {}; +      var headers = mergeHeaders(requestConfig);        extend(config, requestConfig);        config.headers = headers;        config.method = uppercase(config.method); -      extend(headers, -          defaults.headers.common, -          defaults.headers[lowercase(config.method)], -          requestConfig.headers); -        var xsrfValue = isSameDomain(config.url, $browser.url())            ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]            : undefined; @@ -673,7 +668,11 @@ function $HttpProvider() {          // strip content-type if data is undefined          if (isUndefined(config.data)) { -          delete headers['Content-Type']; +          forEach(headers, function(value, header) { +            if (lowercase(header) === 'content-type') { +                delete headers[header]; +            } +          });          }          if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { @@ -729,6 +728,30 @@ function $HttpProvider() {            ? resp            : $q.reject(resp);        } + +      function mergeHeaders(config) { +        var defHeaders = defaults.headers, +            reqHeaders = extend({}, config.headers), +            defHeaderName, lowercaseDefHeaderName, reqHeaderName; + +        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]); + +        // using for-in instead of forEach to avoid unecessary iteration after header has been found +        defaultHeadersIteration: +        for (defHeaderName in defHeaders) { +          lowercaseDefHeaderName = lowercase(defHeaderName); + +          for (reqHeaderName in reqHeaders) { +            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) { +              continue defaultHeadersIteration; +            } +          } + +          reqHeaders[defHeaderName] = defHeaders[defHeaderName]; +        } + +        return reqHeaders; +      }      }      $http.pendingRequests = []; diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index 4ddb3661..8f2642f3 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -717,6 +717,21 @@ describe('$http', function() {          $httpBackend.flush();        }); +      it('should override default headers with custom in a case insensitive manner', function() { +        $httpBackend.expect('POST', '/url', 'messageBody', function(headers) { +          return headers['accept'] == 'Rewritten' && +                 headers['content-type'] == 'Content-Type Rewritten' && +                 headers['Accept'] === undefined && +                 headers['Content-Type'] === undefined; +        }).respond(''); + +        $http({url: '/url', method: 'POST', data: 'messageBody', headers: { +          'accept': 'Rewritten', +          'content-type': 'Content-Type Rewritten' +        }}); +        $httpBackend.flush(); +      }); +        it('should not set XSRF cookie for cross-domain requests', inject(function($browser) {          $browser.cookies('XSRF-TOKEN', 'secret');          $browser.url('http://host.com/base'); @@ -734,7 +749,12 @@ describe('$http', function() {            return !headers.hasOwnProperty('Content-Type');          }).respond(''); +        $httpBackend.expect('POST', '/url2', undefined, function(headers) { +          return !headers.hasOwnProperty('content-type'); +        }).respond(''); +                  $http({url: '/url', method: 'POST'}); +        $http({url: '/url2', method: 'POST', headers: {'content-type': 'Rewritten'}});          $httpBackend.flush();        });  | 
