diff --git a/fetch.js b/fetch.js index c1cab8eedab19eaf750672b49c5c39d5ca58df45..283a3d7147cf8b45b4856c8e350f0921eef84dea 100644 --- a/fetch.js +++ b/fetch.js @@ -5,6 +5,23 @@ return } + function normalizeName(name) { + if (typeof name !== 'string') { + name = name.toString(); + } + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name') + } + return name.toLowerCase() + } + + function normalizeValue(value) { + if (typeof value !== 'string') { + value = value.toString(); + } + return value + } + function Headers(headers) { this.map = {} @@ -24,7 +41,8 @@ } Headers.prototype.append = function(name, value) { - name = name.toLowerCase() + name = normalizeName(name) + value = normalizeValue(value) var list = this.map[name] if (!list) { list = [] @@ -34,24 +52,24 @@ } Headers.prototype['delete'] = function(name) { - delete this.map[name.toLowerCase()] + delete this.map[normalizeName(name)] } Headers.prototype.get = function(name) { - var values = this.map[name.toLowerCase()] + var values = this.map[normalizeName(name)] return values ? values[0] : null } Headers.prototype.getAll = function(name) { - return this.map[name.toLowerCase()] || [] + return this.map[normalizeName(name)] || [] } Headers.prototype.has = function(name) { - return this.map.hasOwnProperty(name.toLowerCase()) + return this.map.hasOwnProperty(normalizeName(name)) } Headers.prototype.set = function(name, value) { - this.map[name.toLowerCase()] = [value] + this.map[normalizeName(name)] = [normalizeValue(value)] } // Instead of iterable for now. @@ -281,6 +299,7 @@ } xhr.open(self.method, self.url, true) + if ('responseType' in xhr && support.blob) { xhr.responseType = 'blob' } diff --git a/test/test.js b/test/test.js index 03b6036c39b2604e0c9cd0c6c298819d260664d5..0e62add96dba004fa6d3437a53f20dc47c77a7ce 100644 --- a/test/test.js +++ b/test/test.js @@ -44,13 +44,78 @@ test('rejects promise for network error', function() { // https://fetch.spec.whatwg.org/#headers-class suite('Headers', function() { - test('headers are case insensitve', function() { + test('headers are case insensitive', function() { var headers = new Headers({'Accept': 'application/json'}) assert.equal(headers.get('ACCEPT'), 'application/json') assert.equal(headers.get('Accept'), 'application/json') assert.equal(headers.get('accept'), 'application/json') }) -}) + test('appends to existing', function() { + var headers = new Headers({'Accept': 'application/json'}) + assert.isFalse(headers.has('Content-Type')) + headers.append('Content-Type', 'application/json') + assert.isTrue(headers.has('Content-Type')) + assert.equal(headers.get('Content-Type'), 'application/json') + }) + test('appends values to existing header name', function() { + var headers = new Headers({'Accept': 'application/json'}) + headers.append('Accept', 'text/plain') + assert.equal(headers.getAll('Accept').length, 2) + assert.equal(headers.getAll('Accept')[0], 'application/json') + assert.equal(headers.getAll('Accept')[1], 'text/plain') + }) + test('sets header name and value', function() { + var headers = new Headers() + headers.set('Content-Type', 'application/json') + assert.equal(headers.get('Content-Type'), 'application/json') + }) + test('returns null on no header found', function() { + var headers = new Headers() + assert.isNull(headers.get('Content-Type')) + }) + test('has headers that are set', function() { + var headers = new Headers() + headers.set('Content-Type', 'application/json') + assert.isTrue(headers.has('Content-Type')) + }) + test('deletes headers', function() { + var headers = new Headers() + headers.set('Content-Type', 'application/json') + assert.isTrue(headers.has('Content-Type')) + headers.delete('Content-Type') + assert.isFalse(headers.has('Content-Type')) + assert.isNull(headers.get('Content-Type')) + }) + test('returns list on getAll when header found', function() { + var headers = new Headers({'Content-Type': 'application/json'}) + assert.isArray(headers.getAll('Content-Type')) + assert.equal(headers.getAll('Content-Type').length, 1) + assert.equal(headers.getAll('Content-Type')[0], 'application/json') + }) + test('returns empty list on getAll when no header found', function() { + var headers = new Headers() + assert.isArray(headers.getAll('Content-Type')) + assert.equal(headers.getAll('Content-Type').length, 0) + }) + test('converts field name to string on set and get', function() { + var headers = new Headers() + headers.set(1, 'application/json') + assert.equal(headers.get(1), 'application/json') + }) + test('converts field value to string on set and get', function() { + var headers = new Headers() + headers.set('Content-Type', 1) + assert.equal(headers.get('Content-Type'), '1') + }) + test('throws TypeError on invalid character in field name', function() { + assert.throws(function() { new Headers({'': ['application/json']}) }, TypeError) + assert.throws(function() { new Headers({'Accept:': ['application/json']}) }, TypeError) + assert.throws(function() { + var headers = new Headers(); + headers.set({field: 'value'}, 'application/json'); + }, TypeError) + }) + }) // https://fetch.spec.whatwg.org/#request-class suite('Request', function() {