116 lines
3.9 KiB
JavaScript
116 lines
3.9 KiB
JavaScript
|
"use strict";
|
||
|
module.exports = fetch;
|
||
|
|
||
|
var asPromise = require("@protobufjs/aspromise"),
|
||
|
inquire = require("@protobufjs/inquire");
|
||
|
|
||
|
var fs = inquire("fs");
|
||
|
|
||
|
/**
|
||
|
* Node-style callback as used by {@link util.fetch}.
|
||
|
* @typedef FetchCallback
|
||
|
* @type {function}
|
||
|
* @param {?Error} error Error, if any, otherwise `null`
|
||
|
* @param {string} [contents] File contents, if there hasn't been an error
|
||
|
* @returns {undefined}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Options as used by {@link util.fetch}.
|
||
|
* @typedef FetchOptions
|
||
|
* @type {Object}
|
||
|
* @property {boolean} [binary=false] Whether expecting a binary response
|
||
|
* @property {boolean} [xhr=false] If `true`, forces the use of XMLHttpRequest
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Fetches the contents of a file.
|
||
|
* @memberof util
|
||
|
* @param {string} filename File path or url
|
||
|
* @param {FetchOptions} options Fetch options
|
||
|
* @param {FetchCallback} callback Callback function
|
||
|
* @returns {undefined}
|
||
|
*/
|
||
|
function fetch(filename, options, callback) {
|
||
|
if (typeof options === "function") {
|
||
|
callback = options;
|
||
|
options = {};
|
||
|
} else if (!options)
|
||
|
options = {};
|
||
|
|
||
|
if (!callback)
|
||
|
return asPromise(fetch, this, filename, options); // eslint-disable-line no-invalid-this
|
||
|
|
||
|
// if a node-like filesystem is present, try it first but fall back to XHR if nothing is found.
|
||
|
if (!options.xhr && fs && fs.readFile)
|
||
|
return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
|
||
|
return err && typeof XMLHttpRequest !== "undefined"
|
||
|
? fetch.xhr(filename, options, callback)
|
||
|
: err
|
||
|
? callback(err)
|
||
|
: callback(null, options.binary ? contents : contents.toString("utf8"));
|
||
|
});
|
||
|
|
||
|
// use the XHR version otherwise.
|
||
|
return fetch.xhr(filename, options, callback);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Fetches the contents of a file.
|
||
|
* @name util.fetch
|
||
|
* @function
|
||
|
* @param {string} path File path or url
|
||
|
* @param {FetchCallback} callback Callback function
|
||
|
* @returns {undefined}
|
||
|
* @variation 2
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Fetches the contents of a file.
|
||
|
* @name util.fetch
|
||
|
* @function
|
||
|
* @param {string} path File path or url
|
||
|
* @param {FetchOptions} [options] Fetch options
|
||
|
* @returns {Promise<string|Uint8Array>} Promise
|
||
|
* @variation 3
|
||
|
*/
|
||
|
|
||
|
/**/
|
||
|
fetch.xhr = function fetch_xhr(filename, options, callback) {
|
||
|
var xhr = new XMLHttpRequest();
|
||
|
xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() {
|
||
|
|
||
|
if (xhr.readyState !== 4)
|
||
|
return undefined;
|
||
|
|
||
|
// local cors security errors return status 0 / empty string, too. afaik this cannot be
|
||
|
// reliably distinguished from an actually empty file for security reasons. feel free
|
||
|
// to send a pull request if you are aware of a solution.
|
||
|
if (xhr.status !== 0 && xhr.status !== 200)
|
||
|
return callback(Error("status " + xhr.status));
|
||
|
|
||
|
// if binary data is expected, make sure that some sort of array is returned, even if
|
||
|
// ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
|
||
|
if (options.binary) {
|
||
|
var buffer = xhr.response;
|
||
|
if (!buffer) {
|
||
|
buffer = [];
|
||
|
for (var i = 0; i < xhr.responseText.length; ++i)
|
||
|
buffer.push(xhr.responseText.charCodeAt(i) & 255);
|
||
|
}
|
||
|
return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer);
|
||
|
}
|
||
|
return callback(null, xhr.responseText);
|
||
|
};
|
||
|
|
||
|
if (options.binary) {
|
||
|
// ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
|
||
|
if ("overrideMimeType" in xhr)
|
||
|
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||
|
xhr.responseType = "arraybuffer";
|
||
|
}
|
||
|
|
||
|
xhr.open("GET", filename);
|
||
|
xhr.send();
|
||
|
};
|