Skip to content

Commit 276a594

Browse files
committed
New: Initial attempt on a backwards compatible fetch implementation with binary support, see #661
1 parent 2d81864 commit 276a594

File tree

14 files changed

+83
-49
lines changed

14 files changed

+83
-49
lines changed

lib/aspromise/.gitignore

-3
This file was deleted.

lib/base64/.gitignore

-3
This file was deleted.

lib/codegen/.gitignore

-3
This file was deleted.

lib/eventemitter/.gitignore

-3
This file was deleted.

lib/fetch/.gitignore

-3
This file was deleted.

lib/fetch/index.js

+78-17
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,99 @@ var fs = inquire("fs");
1515
* @returns {undefined}
1616
*/
1717

18+
/**
19+
* Options as used by {@link util.fetch}.
20+
* @typedef {Object}
21+
* @property {boolean} [binary=false] Whether expecting a binary response or not
22+
*/
23+
1824
/**
1925
* Fetches the contents of a file.
2026
* @memberof util
21-
* @param {string} path File path or url
22-
* @param {FetchCallback} [callback] Callback function
23-
* @returns {Promise<string>} A Promise if `callback` has been omitted, otherwise `undefined`
24-
* @property {function(string, FetchCallback=):Promise<string>} xhr XHR/browser fetch with an identical signature
27+
* @param {string} filename File path or url
28+
* @param {FetchOptions} options Fetch options
29+
* @param {FetchCallback} callback Callback function
30+
* @returns {undefined}
2531
*/
26-
function fetch(path, callback) {
32+
function fetch(filename, options, callback) {
33+
if (typeof options === "function") {
34+
callback = options;
35+
options = {};
36+
} else if (!options)
37+
options = {};
38+
2739
if (!callback)
28-
return asPromise(fetch, this, path); // eslint-disable-line no-invalid-this
40+
return asPromise(fetch, this, filename, options); // eslint-disable-line no-invalid-this
41+
42+
// if a node-like filesystem is present, try it first but fall back to XHR if nothing is found.
2943
if (fs && fs.readFile)
30-
return fs.readFile(path, "utf8", function fetchReadFileCallback(err, contents) {
44+
return fs.readFile(filename, function fetchReadFileCallback(err, contents) {
3145
return err && typeof XMLHttpRequest !== "undefined"
32-
? fetch.xhr(path, callback)
33-
: callback(err, contents);
46+
? fetch.xhr(filename, options, callback)
47+
: err
48+
? callback(err)
49+
: callback(null, options.binary ? contents : contents.toString("utf8"));
3450
});
35-
return fetch.xhr(path, callback);
51+
52+
// use the XHR version otherwise.
53+
return fetch.xhr(filename, options, callback);
3654
}
3755

38-
fetch.xhr = function fetch_xhr(path, callback) {
56+
/**
57+
* Fetches the contents of a file.
58+
* @name util.fetch
59+
* @function
60+
* @param {string} path File path or url
61+
* @param {FetchCallback} callback Callback function
62+
* @returns {undefined}
63+
* @variation 2
64+
*/
65+
66+
/**
67+
* Fetches the contents of a file.
68+
* @name util.fetch
69+
* @function
70+
* @param {string} path File path or url
71+
* @param {FetchOptions} [options] Fetch options
72+
* @returns {Promise<string|Uint8Array>} Promise
73+
* @variation 3
74+
*/
75+
76+
/**/
77+
fetch.xhr = function fetch_xhr(filename, options, callback) {
3978
var xhr = new XMLHttpRequest();
4079
xhr.onreadystatechange /* works everywhere */ = function fetchOnReadyStateChange() {
41-
return xhr.readyState === 4
42-
? xhr.status === 0 || xhr.status === 200
43-
? callback(null, xhr.responseText)
44-
: callback(Error("status " + xhr.status))
45-
: undefined;
80+
81+
if (xhr.readyState !== 4)
82+
return undefined;
83+
4684
// local cors security errors return status 0 / empty string, too. afaik this cannot be
4785
// reliably distinguished from an actually empty file for security reasons. feel free
4886
// to send a pull request if you are aware of a solution.
87+
if (xhr.status !== 0 && xhr.status !== 200)
88+
return callback(Error("status " + xhr.status));
89+
90+
// if binary data is expected, make sure that some sort of array is returned, even if
91+
// ArrayBuffers are not supported. the binary string fallback, however, is unsafe.
92+
if (options.binary) {
93+
var buffer = xhr.response;
94+
if (!buffer) {
95+
buffer = [];
96+
for (var i = 0; i < xhr.responseText.length; ++i)
97+
buffer.push(xhr.responseText.charCodeAt(i) & 255);
98+
}
99+
return callback(null, typeof Uint8Array !== "undefined" ? new Uint8Array(buffer) : buffer);
100+
}
101+
return callback(null, xhr.responseText);
49102
};
50-
xhr.open("GET", path);
103+
104+
if (options.binary) {
105+
// ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Receiving_binary_data_in_older_browsers
106+
if ("overrideMimeType" in xhr)
107+
xhr.overrideMimeType("text/plain; charset=x-user-defined");
108+
xhr.responseType = "arraybuffer";
109+
}
110+
111+
xhr.open("GET", filename);
51112
xhr.send();
52113
};

lib/fetch/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@protobufjs/fetch",
33
"description": "Fetches the contents of a file accross node and browsers.",
4-
"version": "1.0.4",
4+
"version": "1.0.5",
55
"author": "Daniel Wirtz <[email protected]>",
66
"repository": {
77
"type": "git",

lib/fetch/tests/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ tape.test("fetch", function(test) {
1010
test.ok(promise instanceof Promise, "should return a promise if callback has been omitted");
1111
}
1212

13-
// TODO
13+
// TODO - some what to test this properly?
1414

1515
test.end();
1616
});

lib/inquire/.gitignore

-3
This file was deleted.

lib/path/.gitignore

-3
This file was deleted.

lib/pool/.gitignore

-3
This file was deleted.

lib/utf8/.gitignore

-3
This file was deleted.

scripts/bundle.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ var buffer = require("vinyl-buffer");
1313
var vinylfs = require("vinyl-fs");
1414
var source = require("vinyl-source-stream");
1515

16+
var zopfli = require("node-zopfli");
17+
1618
var pkg = require(__dirname + "/../package.json");
1719

1820
var license = [
@@ -86,9 +88,6 @@ function bundle(options) {
8688
.on("error", gutil.log);
8789
}
8890

89-
var fs = require("fs");
90-
var zopfli = require("node-zopfli");
91-
9291
/**
9392
* Compresses a file using zopfli gzip.
9493
* @param {string} sourceFile Source file

tests/node/lib_fetch.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require("../../lib/fetch/tests");

0 commit comments

Comments
 (0)