aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2023-05-19 12:12:54 -0700
committerGravatar GitHub <noreply@github.com> 2023-05-19 12:12:54 -0700
commitbf0f5c9b3d536c16561525ec281ad5e61acdb5e3 (patch)
treef4be07d0095a1105c3233df534a98ee394895b84
parent9b28d2009db0bc5502acd6eab074e6f44014ab0f (diff)
downloadbun-bf0f5c9b3d536c16561525ec281ad5e61acdb5e3.tar.gz
bun-bf0f5c9b3d536c16561525ec281ad5e61acdb5e3.tar.zst
bun-bf0f5c9b3d536c16561525ec281ad5e61acdb5e3.zip
Make `node-fetch` polyfill better (#2962)
* Make `node-fetch` polyfill better * fixup * Test using localhost * Add comment --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
-rw-r--r--src/node-fallbacks/node-fetch.js92
-rw-r--r--test/js/node/fs/node-fetch.test.js21
2 files changed, 109 insertions, 4 deletions
diff --git a/src/node-fallbacks/node-fetch.js b/src/node-fallbacks/node-fetch.js
index 4e5e96bdd..f124e6461 100644
--- a/src/node-fallbacks/node-fetch.js
+++ b/src/node-fallbacks/node-fetch.js
@@ -1,8 +1,92 @@
-var fetchHandler = globalThis.fetch;
+var { Headers, Request, Response, Blob, File = Blob, FormData, fetch: realFetch } = globalThis;
if ("Bun" in globalThis) {
- fetchHandler = Bun.fetch;
+ realFetch = Bun.fetch;
}
-export default fetchHandler;
-export { fetchHandler as fetch };
+function fetch(...args) {
+ // require("node-fetch") returns the default export which means we need to
+ // repeat the ESM exports onto it.
+ //
+ // We don't want to copy that onto the global fetch object, so we wrap it.
+ return realFetch(...args);
+}
+
+class AbortError extends DOMException {
+ constructor(message) {
+ super(message, "AbortError");
+ }
+}
+
+class FetchBaseError extends Error {
+ constructor(message, type) {
+ super(message);
+ this.type = type;
+ }
+}
+
+class FetchError extends FetchBaseError {
+ constructor(message, type, systemError) {
+ super(message, type);
+ this.code = systemError?.code;
+ }
+}
+
+function blobFrom(path, options) {
+ if ("Bun" in globalThis) {
+ return Promise.resolve(Bun.file(data));
+ }
+
+ return fetch(path, options).then(response => response.blob());
+}
+
+function blobFromSync(path, options) {
+ if ("Bun" in globalThis) {
+ return Bun.file(data);
+ }
+
+ return fetch(path, options).then(response => response.blob());
+}
+
+var fileFrom = blobFrom;
+var fileFromSync = blobFromSync;
+
+function isRedirect(code) {
+ return code === 301 || code === 302 || code === 303 || code === 307 || code === 308;
+}
+
+export default Object.assign(fetch, {
+ AbortError,
+ Blob,
+ FetchBaseError,
+ FetchError,
+ File,
+ FormData,
+ Headers,
+ Request,
+ Response,
+ blobFrom,
+ blobFromSync,
+ fileFrom,
+ fileFromSync,
+ isRedirect,
+ [Symbol.for("CommonJS")]: 0,
+});
+
+export {
+ AbortError,
+ Blob,
+ FetchBaseError,
+ FetchError,
+ File,
+ FormData,
+ Headers,
+ Request,
+ Response,
+ blobFrom,
+ blobFromSync,
+ fileFrom,
+ fileFromSync,
+ isRedirect,
+ fetch,
+};
diff --git a/test/js/node/fs/node-fetch.test.js b/test/js/node/fs/node-fetch.test.js
new file mode 100644
index 000000000..11c5e0ed3
--- /dev/null
+++ b/test/js/node/fs/node-fetch.test.js
@@ -0,0 +1,21 @@
+import { fetch, Response, Request, Headers } from "node-fetch";
+
+import { test, expect } from "bun:test";
+
+test("node-fetch", () => {
+ expect(Response).toBe(globalThis.Response);
+ expect(Request).toBe(globalThis.Request);
+ expect(Headers).toBe(globalThis.Headers);
+});
+
+test("node-fetch fetches", async () => {
+ const server = Bun.serve({
+ port: 0,
+ fetch(req, server) {
+ server.stop();
+ return new Response();
+ },
+ });
+ expect(await fetch("http://" + server.hostname + ":" + server.port)).toBeInstanceOf(Response);
+ server.stop(true);
+});