From bbff7403fbf46f9ad92240ac213df8d30ef31b64 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Thu, 20 Sep 2018 02:56:13 +0200 Subject: update packages --- node_modules/stream-http/lib/capability.js | 4 +++ node_modules/stream-http/lib/request.js | 47 ++++++++++++++++++------- node_modules/stream-http/lib/response.js | 56 ++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 20 deletions(-) (limited to 'node_modules/stream-http/lib') diff --git a/node_modules/stream-http/lib/capability.js b/node_modules/stream-http/lib/capability.js index 00dfe7696..3a17334e6 100644 --- a/node_modules/stream-http/lib/capability.js +++ b/node_modules/stream-http/lib/capability.js @@ -1,5 +1,9 @@ exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream) +exports.writableStream = isFunction(global.WritableStream) + +exports.abortController = isFunction(global.AbortController) + exports.blobConstructor = false try { new Blob([new ArrayBuffer(1)]) diff --git a/node_modules/stream-http/lib/request.js b/node_modules/stream-http/lib/request.js index 36ad12db9..4f097dfa3 100644 --- a/node_modules/stream-http/lib/request.js +++ b/node_modules/stream-http/lib/request.js @@ -38,9 +38,8 @@ var ClientRequest = module.exports = function (opts) { var preferBinary var useFetch = true - if (opts.mode === 'disable-fetch' || 'timeout' in opts) { - // If the use of XHR should be preferred and includes preserving the 'content-type' header. - // Force XHR to be used since the Fetch API does not yet support timeouts. + if (opts.mode === 'disable-fetch' || ('requestTimeout' in opts && !capability.abortController)) { + // If the use of XHR should be preferred. Not typically needed. useFetch = false preferBinary = true } else if (opts.mode === 'prefer-streaming') { @@ -57,6 +56,7 @@ var ClientRequest = module.exports = function (opts) { throw new Error('Invalid value for opts.mode') } self._mode = decideMode(preferBinary, useFetch) + self._fetchTimer = null self.on('finish', function () { self._onFinish() @@ -102,7 +102,9 @@ ClientRequest.prototype._onFinish = function () { var headersObj = self._headers var body = null if (opts.method !== 'GET' && opts.method !== 'HEAD') { - if (capability.blobConstructor) { + if (capability.arraybuffer) { + body = toArrayBuffer(Buffer.concat(self._body)) + } else if (capability.blobConstructor) { body = new global.Blob(self._body.map(function (buffer) { return toArrayBuffer(buffer) }), { @@ -129,17 +131,36 @@ ClientRequest.prototype._onFinish = function () { }) if (self._mode === 'fetch') { + var signal = null + var fetchTimer = null + if (capability.abortController) { + var controller = new AbortController() + signal = controller.signal + self._fetchAbortController = controller + + if ('requestTimeout' in opts && opts.requestTimeout !== 0) { + self._fetchTimer = global.setTimeout(function () { + self.emit('requestTimeout') + if (self._fetchAbortController) + self._fetchAbortController.abort() + }, opts.requestTimeout) + } + } + global.fetch(self._opts.url, { method: self._opts.method, headers: headersList, body: body || undefined, mode: 'cors', - credentials: opts.withCredentials ? 'include' : 'same-origin' + credentials: opts.withCredentials ? 'include' : 'same-origin', + signal: signal }).then(function (response) { self._fetchResponse = response self._connect() }, function (reason) { - self.emit('error', reason) + global.clearTimeout(self._fetchTimer) + if (!self._destroyed) + self.emit('error', reason) }) } else { var xhr = self._xhr = new global.XMLHttpRequest() @@ -162,10 +183,10 @@ ClientRequest.prototype._onFinish = function () { if (self._mode === 'text' && 'overrideMimeType' in xhr) xhr.overrideMimeType('text/plain; charset=x-user-defined') - if ('timeout' in opts) { - xhr.timeout = opts.timeout + if ('requestTimeout' in opts) { + xhr.timeout = opts.requestTimeout xhr.ontimeout = function () { - self.emit('timeout') + self.emit('requestTimeout') } } @@ -239,7 +260,7 @@ ClientRequest.prototype._connect = function () { if (self._destroyed) return - self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode) + self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode, self._fetchTimer) self._response.on('error', function(err) { self.emit('error', err) }) @@ -257,12 +278,13 @@ ClientRequest.prototype._write = function (chunk, encoding, cb) { ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () { var self = this self._destroyed = true + global.clearTimeout(self._fetchTimer) if (self._response) self._response._destroyed = true if (self._xhr) self._xhr.abort() - // Currently, there isn't a way to truly abort a fetch. - // If you like bikeshedding, see https://github.com/whatwg/fetch/issues/27 + else if (self._fetchAbortController) + self._fetchAbortController.abort() } ClientRequest.prototype.end = function (data, encoding, cb) { @@ -301,6 +323,5 @@ var unsafeHeaders = [ 'trailer', 'transfer-encoding', 'upgrade', - 'user-agent', 'via' ] diff --git a/node_modules/stream-http/lib/response.js b/node_modules/stream-http/lib/response.js index e5d057d24..17d1fb716 100644 --- a/node_modules/stream-http/lib/response.js +++ b/node_modules/stream-http/lib/response.js @@ -10,7 +10,7 @@ var rStates = exports.readyStates = { DONE: 4 } -var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) { +var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode, fetchTimer) { var self = this stream.Readable.call(self) @@ -35,30 +35,64 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) { self.statusCode = response.status self.statusMessage = response.statusText - response.headers.forEach(function(header, key){ + response.headers.forEach(function (header, key){ self.headers[key.toLowerCase()] = header self.rawHeaders.push(key, header) }) + if (capability.writableStream) { + var writable = new WritableStream({ + write: function (chunk) { + return new Promise(function (resolve, reject) { + if (self._destroyed) { + reject() + } else if(self.push(new Buffer(chunk))) { + resolve() + } else { + self._resumeFetch = resolve + } + }) + }, + close: function () { + global.clearTimeout(fetchTimer) + if (!self._destroyed) + self.push(null) + }, + abort: function (err) { + if (!self._destroyed) + self.emit('error', err) + } + }) - // TODO: this doesn't respect backpressure. Once WritableStream is available, this can be fixed + try { + response.body.pipeTo(writable).catch(function (err) { + global.clearTimeout(fetchTimer) + if (!self._destroyed) + self.emit('error', err) + }) + return + } catch (e) {} // pipeTo method isn't defined. Can't find a better way to feature test this + } + // fallback for when writableStream or pipeTo aren't available var reader = response.body.getReader() function read () { reader.read().then(function (result) { if (self._destroyed) return if (result.done) { + global.clearTimeout(fetchTimer) self.push(null) return } self.push(new Buffer(result.value)) read() - }).catch(function(err) { - self.emit('error', err) + }).catch(function (err) { + global.clearTimeout(fetchTimer) + if (!self._destroyed) + self.emit('error', err) }) } read() - } else { self._xhr = xhr self._pos = 0 @@ -102,7 +136,15 @@ var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) { inherits(IncomingMessage, stream.Readable) -IncomingMessage.prototype._read = function () {} +IncomingMessage.prototype._read = function () { + var self = this + + var resolve = self._resumeFetch + if (resolve) { + self._resumeFetch = null + resolve() + } +} IncomingMessage.prototype._onXHRProgress = function () { var self = this -- cgit v1.2.3