From 3a1cf20becdea26ce7b26d9ecfff1b4d3cf27d6c Mon Sep 17 00:00:00 2001 From: Erik Arvidsson Date: Sat, 25 Jun 2016 07:46:46 +0800 Subject: [PATCH] JS: Make fetch response headers a Map again (#1898) Since we are using browser fetch when available it makes more sense to use a Map. --- js/src/browser/fetch.js | 21 +++++++++++++++++---- js/src/fetch.js | 12 ++++++++++-- js/src/http-batch-store.js | 4 ++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/js/src/browser/fetch.js b/js/src/browser/fetch.js index b509ebf226..2ea57dac54 100644 --- a/js/src/browser/fetch.js +++ b/js/src/browser/fetch.js @@ -4,6 +4,7 @@ // Licensed under the Apache License, version 2.0: // http://www.apache.org/licenses/LICENSE-2.0 +import {notNull} from '../assert.js'; export type FetchOptions = { method?: string, @@ -12,7 +13,7 @@ export type FetchOptions = { withCredentials? : boolean, }; -type Response = {headers: {[key: string]: string}, buf: T}; +type Response = {headers: Map, buf: T}; type TextResponse = Response; type BufResponse = Response; @@ -22,12 +23,12 @@ function fetch(url: string, responseType: string, options: FetchOptions = {}) xhr.responseType = responseType; const method = options.method || 'GET'; xhr.open(method, url, true); - const p = new Promise((res, rej) => { + const p = new Promise((resolve, reject) => { xhr.onloadend = () => { if (xhr.status >= 200 && xhr.status < 300) { - res({headers: res.headers, buf: xhr.response}); + resolve({headers: makeHeaders(xhr), buf: xhr.response}); } else { - rej(new Error(`HTTP Error: ${xhr.status}`)); + reject(new Error(`HTTP Error: ${xhr.status}`)); } }; }); @@ -46,6 +47,7 @@ function fetch(url: string, responseType: string, options: FetchOptions = {}) export function fetchText(url: string, options: FetchOptions = {}): Promise { if (self.fetch) { return self.fetch(url, options) + // resp.headers is a Headers which is a multi map, which is similar enough for now. .then(resp => ({headers: resp.headers, buf: resp.text()})); } @@ -55,8 +57,19 @@ export function fetchText(url: string, options: FetchOptions = {}): Promise { if (self.fetch) { return self.fetch(url, options) + // resp.headers is a Headers which is a multi map, which is similar enough for now. .then(resp => ({headers: resp.headers, buf: new Uint8Array(resp.arrayBuffer())})); } return fetch(url, 'arraybuffer', options); } + +function makeHeaders(xhr: XMLHttpRequest): Map { + const m = new Map(); + const headers = xhr.getAllResponseHeaders().split(/\r\n/); // spec requires \r\n + for (const header of headers) { + const [, name, value] = notNull(header.match(/([^:]+): (.*)/)); + m.set(name, value); + } + return m; +} diff --git a/js/src/fetch.js b/js/src/fetch.js index 921781ef4e..f7839df67c 100644 --- a/js/src/fetch.js +++ b/js/src/fetch.js @@ -15,10 +15,18 @@ export type FetchOptions = { withCredentials? : boolean, }; -type Response = {headers: {[key: string]: string}, buf: T}; +type Response = {headers: Map, buf: T}; type TextResponse = Response; type BufResponse = Response; +function objectToMap(object: {[key: string]: T}): Map { + const m = new Map(); + for (const k in object) { + m.set(k, object[k]); + } + return m; +} + function fetch(url: string, options: FetchOptions = {}): Promise { const opts: any = parse(url); opts.method = options.method || 'GET'; @@ -54,7 +62,7 @@ function fetch(url: string, options: FetchOptions = {}): Promise { offset += size; }); res.on('end', () => { - resolve({headers: res.headers, buf: Bytes.subarray(buf, 0, offset)}); + resolve({headers: objectToMap(res.headers), buf: Bytes.subarray(buf, 0, offset)}); }); }); req.on('error', err => { diff --git a/js/src/http-batch-store.js b/js/src/http-batch-store.js index da7b5c84e4..60404d6f1e 100644 --- a/js/src/http-batch-store.js +++ b/js/src/http-batch-store.js @@ -159,8 +159,8 @@ export class Delegate { } } -function checkVersion(headers: {[key: string]: string}): ?Error { - const version = headers[versionHeader]; +function checkVersion(headers: Map): ?Error { + const version = headers.get(versionHeader); if (version !== nomsVersion) { return new Error( `SDK version ${nomsVersion} is not compatible with data of version ${version}.`);