From c8441c6638365cc5d88c2bbeafe182cfd507361b Mon Sep 17 00:00:00 2001 From: Sven Slootweg Date: Tue, 18 Feb 2020 00:45:30 +0100 Subject: [PATCH] Fix some conversion errors --- lib/bhttp.js | 44 +++++++++++++++++++++++++++++++++++++++----- src/bhttp.js | 30 +++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/lib/bhttp.js b/lib/bhttp.js index 509b15f..797335e 100644 --- a/lib/bhttp.js +++ b/lib/bhttp.js @@ -4,6 +4,14 @@ // FIXME: Are arrays of streams in `data` correctly recognized as being streams? // Core modules +function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } + +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } + +function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } + +function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } + var urlUtil = require("url"); var querystring = require("querystring"); @@ -91,6 +99,32 @@ function shallowClone(object) { return Object.assign({}, object); } +function iterateValues(object) { + if (object == null) { + return []; + } else { + return Object.values(object); + } +} + +function assign() { + for (var _len = arguments.length, objects = new Array(_len), _key = 0; _key < _len; _key++) { + objects[_key] = arguments[_key]; + } + + var validObjects = objects.filter(function (object) { + return object != null; + }); + + if (validObjects.length === 0) { + return {}; + } else if (validObjects.length === 1) { + return validObjects[0]; + } else { + return Object.assign.apply(Object, _toConsumableArray(validObjects)); + } +} + var ofTypes = function ofTypes(obj, types) { var match = false; var _iteratorNormalCompletion = true; @@ -210,7 +244,7 @@ var prepareUrl = function prepareUrl(request, response, requestState) { return Promise.try(function () { // Parse the specified URL, and use the resulting information to build a complete `options` object var urlOptions = urlUtil.parse(request.url, true); - Object.assign(request.options, { + assign(request.options, { hostname: urlOptions.hostname, port: urlOptions.port }); @@ -291,13 +325,13 @@ var preparePayload = function preparePayload(request, response, requestState) { var multipart = request.options.forceMultipart || request.options.files != null; // Similarly, if any of the formFields values are either a Stream or a Buffer, we will assume that the form should be sent as multipart. - multipart = multipart || Object.values(request.options.formFields).some(function (item) { + multipart = multipart || iterateValues(request.options.formFields).some(function (item) { return item instanceof Buffer || isStream(item); }); // Really, 'files' and 'formFields' are the same thing - they mostly have different names for 1) clarity and 2) multipart detection. We combine them here. - Object.assign(request.options.formFields, request.options.files); // For a last sanity check, we want to know whether there are any Stream objects in our form data *at all* - these can't be used when encodeJSON is enabled. + assign(request.options.formFields, request.options.files); // For a last sanity check, we want to know whether there are any Stream objects in our form data *at all* - these can't be used when encodeJSON is enabled. - var containsStreams = Object.values(request.options.formFields).some(function (item) { + var containsStreams = iterateValues(request.options.formFields).some(function (item) { return isStream(item); }); @@ -379,7 +413,7 @@ var preparePayload = function preparePayload(request, response, requestState) { if (headers["content-transfer-encoding"] === "chunked" && !request.options.allowChunkedMultipart) { return Promise.reject(addErrorData(new bhttpErrors.MultipartError("Most servers do not support chunked transfer encoding for multipart/form-data payloads, and we could not determine the length of all the input streams. See the documentation for more information."), request, response, requestState)); } else { - Object.assign(request.options.headers, headers); + assign(request.options.headers, headers); return Promise.resolve(); } }); diff --git a/src/bhttp.js b/src/bhttp.js index 3e55ef1..fd5299e 100644 --- a/src/bhttp.js +++ b/src/bhttp.js @@ -86,6 +86,26 @@ function shallowClone(object) { return Object.assign({}, object); } +function iterateValues(object) { + if (object == null) { + return []; + } else { + return Object.values(object); + } +} + +function assign(...objects) { + let validObjects = objects.filter((object) => object != null); + + if (validObjects.length === 0) { + return {}; + } else if (validObjects.length === 1) { + return validObjects[0]; + } else { + return Object.assign(...validObjects); + } +} + const ofTypes = function(obj, types) { let match = false; for (let type of types) { @@ -176,7 +196,7 @@ const prepareUrl = function(request, response, requestState) { // Parse the specified URL, and use the resulting information to build a complete `options` object const urlOptions = urlUtil.parse(request.url, true); - Object.assign(request.options, {hostname: urlOptions.hostname, port: urlOptions.port}); + assign(request.options, {hostname: urlOptions.hostname, port: urlOptions.port}); request.options.path = urlUtil.format({pathname: urlOptions.pathname, query: request.options.query != null ? request.options.query : urlOptions.query}); request.protocol = urlOptions.protocol.replace(/:$/, ""); @@ -234,13 +254,13 @@ const preparePayload = function(request, response, requestState) { let multipart = request.options.forceMultipart || (request.options.files != null); // Similarly, if any of the formFields values are either a Stream or a Buffer, we will assume that the form should be sent as multipart. - multipart = multipart || Object.values(request.options.formFields).some((item) => item instanceof Buffer || isStream(item)); + multipart = multipart || iterateValues(request.options.formFields).some((item) => item instanceof Buffer || isStream(item)); // Really, 'files' and 'formFields' are the same thing - they mostly have different names for 1) clarity and 2) multipart detection. We combine them here. - Object.assign(request.options.formFields, request.options.files); + assign(request.options.formFields, request.options.files); // For a last sanity check, we want to know whether there are any Stream objects in our form data *at all* - these can't be used when encodeJSON is enabled. - const containsStreams = Object.values(request.options.formFields).some((item) => isStream(item)); + const containsStreams = iterateValues(request.options.formFields).some((item) => isStream(item)); if (request.options.encodeJSON && containsStreams) { return Promise.reject(new bhttpErrors.ConflictingOptionsError("Sending a JSON-encoded payload containing data from a stream is not currently supported.", undefined, "Either don't use encodeJSON, or read your stream into a string or Buffer.")); @@ -298,7 +318,7 @@ const preparePayload = function(request, response, requestState) { if ((headers["content-transfer-encoding"] === "chunked") && !request.options.allowChunkedMultipart) { return Promise.reject(addErrorData(new bhttpErrors.MultipartError("Most servers do not support chunked transfer encoding for multipart/form-data payloads, and we could not determine the length of all the input streams. See the documentation for more information."), request, response, requestState)); } else { - Object.assign(request.options.headers, headers); + assign(request.options.headers, headers); return Promise.resolve(); } });