diff --git a/README.md b/README.md index 1966279..f7cea96 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ The default plugins under node are `[stringify, headers, cookieJar, unzip, conca **Options using browser transport** * **withCredentials** Send cookies with CORS requests (default: `false`) +* **responseType** Set the XHR `responseType` (default: `undefined`) #### Short-hand Methods diff --git a/lib/browser.ts b/lib/browser.ts index c74e4cf..0208b0c 100644 --- a/lib/browser.ts +++ b/lib/browser.ts @@ -16,6 +16,7 @@ function open (request: Request) { return new Promise(function (resolve, reject) { const url = request.fullUrl() const method = request.method + const responseType = request.options.responseType // Loading HTTP resources from HTTPS is restricted and uncatchable. if (window.location.protocol === 'https:' && /^http\:/.test(url)) { @@ -28,7 +29,7 @@ function open (request: Request) { return resolve({ status: xhr.status === 1223 ? 204 : xhr.status, headers: getHeaders(xhr.getAllResponseHeaders()), - body: xhr.responseText, + body: responseType ? xhr.response : xhr.responseText, url: xhr.responseURL }) } @@ -76,6 +77,16 @@ function open (request: Request) { xhr.withCredentials = true } + if (responseType) { + try { + xhr.responseType = responseType + } finally { + if (xhr.responseType !== responseType) { + throw request.error(`Unsupported response type: ${responseType}`, 'ERESPONSETYPE') + } + } + } + // Set all headers with original casing. Object.keys(request.headers).forEach(function (header) { xhr.setRequestHeader(request.name(header), request.get(header)) diff --git a/lib/plugins/common.ts b/lib/plugins/common.ts index 9866579..879aa77 100644 --- a/lib/plugins/common.ts +++ b/lib/plugins/common.ts @@ -100,6 +100,10 @@ function stringifyRequest (request: Request) { function parseResponse (response: Response) { const body = response.body + if (typeof body !== 'string') { + return + } + if (body === '') { response.body = null diff --git a/popsicle.js b/popsicle.js index 6bd02ce..a24fb1a 100644 --- a/popsicle.js +++ b/popsicle.js @@ -988,6 +988,7 @@ function open(request) { return new Promise(function (resolve, reject) { var url = request.fullUrl(); var method = request.method; + var responseType = request.options.responseType; if (window.location.protocol === 'https:' && /^http\:/.test(url)) { return reject(request.error("The request to \"" + url + "\" was blocked", 'EBLOCKED')); } @@ -996,7 +997,7 @@ function open(request) { return resolve({ status: xhr.status === 1223 ? 204 : xhr.status, headers: get_headers_1.parse(xhr.getAllResponseHeaders()), - body: xhr.responseText, + body: responseType ? xhr.response : xhr.responseText, url: xhr.responseURL }); }; @@ -1033,6 +1034,16 @@ function open(request) { if (request.options.withCredentials) { xhr.withCredentials = true; } + if (responseType) { + try { + xhr.responseType = responseType; + } + finally { + if (xhr.responseType !== responseType) { + throw request.error("Unsupported response type: " + responseType, 'ERESPONSETYPE'); + } + } + } Object.keys(request.headers).forEach(function (header) { xhr.setRequestHeader(request.name(header), request.get(header)); }); diff --git a/test/index.ts b/test/index.ts index 868a3b0..65cd3b0 100644 --- a/test/index.ts +++ b/test/index.ts @@ -561,7 +561,7 @@ test('response body', function (t) { }) }) - t.test('should unzip contents', function (t) { + t.test('unzip contents', function (t) { return popsicle({ url: REMOTE_URL + '/echo/zip', body: fs.createReadStream(filename) @@ -572,7 +572,7 @@ test('response body', function (t) { }) }) - t.test('should unzip with gzip encoding', function (t) { + t.test('unzip with gzip encoding', function (t) { return popsicle({ url: REMOTE_URL + '/echo/zip', body: fs.createReadStream(filename), @@ -585,6 +585,33 @@ test('response body', function (t) { t.equal(res.body, filecontents) }) }) + } else { + t.test('browser response type', function (t) { + return popsicle({ + url: REMOTE_URL + '/text', + options: { + responseType: 'arraybuffer' + } + }) + .then(function (res) { + t.ok(res.body instanceof ArrayBuffer) + }) + }) + + t.test('throw on unsupported response type', function (t) { + t.plan(2) + + return popsicle({ + url: REMOTE_URL + '/text', + options: { + responseType: 'foobar' + } + }) + .catch(function (err) { + t.equal(err.message, 'Unsupported response type: foobar') + t.equal(err.type, 'ERESPONSETYPE') + }) + }) } })