Skip to content

Commit

Permalink
feat(proxy): export fetch and createFetch (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Dec 24, 2023
1 parent 16f01ce commit b5ca4c3
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 58 deletions.
56 changes: 36 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ You have two ways to do this:

Using the polyfill method, we can ensure global fetch is available in the environment and all files. Natives are always preferred.

**Note:** I don't recommend this if you are authoring a library! Please prefer explicit methods.
**Note:** I don't recommend this if you are authoring a library! Please prefer the explicit methods.

```js
// ESM
Expand All @@ -109,33 +109,51 @@ require("node-fetch-native/polyfill");

Node.js has no built-in support for HTTP Proxies for fetch (see [nodejs/undici#1650](https://github.com/nodejs/undici/issues/1650) and [nodejs/node#8381](https://github.com/nodejs/node/issues/8381))

This package bundles a compact and simple proxy supported for both Node.js versions without native fetch using [HTTP Agent](https://github.com/TooTallNate/proxy-agents/tree/main/packages/proxy-agent) and versions with native fetch using [Undici Proxy Agent](https://undici.nodejs.org/#/docs/api/ProxyAgent).
This package bundles a compact and simple proxy-supported solution for both Node.js versions without native fetch using [HTTP Agent](https://github.com/TooTallNate/proxy-agents/tree/main/packages/proxy-agent) and versions with native fetch using [Undici Proxy Agent](https://undici.nodejs.org/#/docs/api/ProxyAgent).

**Usage:**
By default, `HTTP_PROXY`, `http_proxy`, `HTTPS_PROXY`, and `https_proxy` environment variables will be used for the proxy and if not any of them are set, the proxy will be disabled.

> [!NOTE]
> Using export conditions, this utility adds proxy support for Node.js and for other runtimes, it will simply return native fetch.
> [!IMPORTANT]
> Proxy support is under development. Check [unjs/node-fetch-native#107](https://github.com/unjs/node-fetch-native/issues/107) for the roadmap and contributing!
### `fetch` with proxy support

You can simply import `{ fetch }` from `node-fetch-native/proxy` with a preconfigured `fetch` function that has proxy support.

```ts
import { fetch } from "node-fetch-native"; // or use global fetch
import { createProxy } from "node-fetch-native/proxy";
import { fetch } from "node-fetch-native/proxy";

// Uses HTTPS_PROXY or HTTP_PROXY environment variables
const proxy = createProxy();
console.log(await fetch("https://icanhazip.com").then((r) => r.text());
```
// const proxy = createProxy({ url: "http://localhost:8080" });
### `createFetch` utility
You can use `createFetch` utility to intantiate a `fetch` instance with custom proxy options.
```ts
import { createFetch } from "node-fetch-native/proxy";

const fetch = createFetch({ url: "http://localhost:9080" });

await fetch("https://google.com", {
...proxy,
});
console.log(await fetch("https://icanhazip.com").then((r) => r.text());
```
`createProxy` returns an object with `agent` for older Node.js versions and `dispatcher` keys for newer Node.js versions with Undici and native fetch.
### `createProxy` utility
If no `url` option is provided, `HTTPS_PROXY` or `HTTP_PROXY` (or lowercase) environment variables will be used, and if they also are not set, both `agent` and `dispatcher` values will be undefined.
`createProxy` returns an object with `agent` and `dispatcher` keys that can be passed as fetch options.
> [!NOTE]
> Using export conditions, this utility works in Node.js and for other runtimes, it will simply return a stubbed version as most of the other runtimes now support HTTP proxy out of the box!
```ts
import { fetch } from "node-fetch-native";
import { createProxy } from "node-fetch-native/proxy";

> [!NOTE]
> Proxy support is under development. Check [unjs/node-fetch-native#107](https://github.com/unjs/node-fetch-native/issues/107) for the roadmap and contributing!
const proxy = createProxy();
// const proxy = createProxy({ url: "http://localhost:8080" });

console.log(await fetch("https://icanhazip.com", { ...proxy }).then((r) => r.text());
```
## Alias to `node-fetch`
Expand Down Expand Up @@ -184,9 +202,7 @@ Using [pnpm.overrides](https://pnpm.io/package_json#pnpmoverrides):
## License
Made with 💛

[node-fetch is published under the MIT license](https://github.com/node-fetch/node-fetch/blob/main/LICENSE.md)
Made with 💛 Published under the [MIT](./LICENSE) license.
<!-- Badges -->
Expand Down
1 change: 1 addition & 0 deletions build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default defineBuildConfig({
"src/proxy",
"src/proxy-stub",
],
externals: ["node-fetch-native"],
hooks: {
async "build:done"(ctx) {
// Save few bytes from dist...
Expand Down
8 changes: 0 additions & 8 deletions lib/proxy.d.cts

This file was deleted.

8 changes: 0 additions & 8 deletions lib/proxy.d.mts

This file was deleted.

16 changes: 16 additions & 0 deletions lib/proxy.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type * as http from "node:http";
import type * as https from "node:https";
import type * as undici from "undici";

export type ProxyOptions = { url?: string };

export declare const createProxy: (opts?: ProxyOptions) => {
agent: http.Agent | https.Agent | undefined;
dispatcher: undici.Dispatcher | undefined;
};

export declare const createFetch: (
proxyOptions?: ProxyOptions,
) => typeof globalThis.fetch;

export declare const fetch: typeof globalThis.fetch;
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,21 +82,21 @@
"./proxy": {
"node": {
"import": {
"types": "./lib/proxy.d.mts",
"types": "./lib/proxy.d.ts",
"default": "./dist/proxy.cjs"
},
"require": {
"types": "./lib/proxy.d.cts",
"types": "./lib/proxy.d.ts",
"default": "./dist/proxy.cjs"
}
},
"default": {
"import": {
"types": "./lib/proxy.d.mts",
"types": "./lib/proxy.d.ts",
"default": "./dist/proxy-stub.mjs"
},
"require": {
"types": "./lib/proxy.d.cts",
"types": "./lib/proxy.d.ts",
"default": "./dist/proxy-stub.cjs"
}
}
Expand Down Expand Up @@ -141,4 +141,4 @@
"vitest": "^1.1.0"
},
"packageManager": "pnpm@8.12.1"
}
}
2 changes: 1 addition & 1 deletion proxy.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./lib/proxy.mjs";
export * from "./lib/proxy";
6 changes: 6 additions & 0 deletions src/proxy-stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ export function createProxy() {
dispatcher: undefined,
};
}

export function createFetch() {
return globalThis.fetch;
}

export const fetch = globalThis.fetch;
15 changes: 14 additions & 1 deletion src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import { ProxyAgent as UndiciProxyAgent } from "undici";
import { Agent, AgentConnectOpts } from "agent-base";
import { HttpProxyAgent } from "http-proxy-agent";
import { HttpsProxyAgent } from "https-proxy-agent";
import type { ProxyOptions } from "../proxy";
import { fetch as _fetch } from "node-fetch-native";

export function createProxy(opts: { url?: string } = {}) {
export function createProxy(opts: ProxyOptions = {}) {
const uri =
opts.url ||
process.env.HTTPS_PROXY ||
Expand All @@ -32,6 +34,17 @@ export function createProxy(opts: { url?: string } = {}) {
};
}

export function createFetch(proxyOptions: ProxyOptions = {}) {
const proxy = createProxy(proxyOptions);
return (url, fetchOptions) => _fetch(url, { ...proxy, ...fetchOptions });
}

export const fetch = createFetch({});

// ----------------------------------------------
// Utils
// ----------------------------------------------

export function debug(...args: any[]) {
if (process.env.debug) {
debug("[node-fetch-native] [proxy]", ...args);
Expand Down
14 changes: 3 additions & 11 deletions test/proxy.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import { fetch } from "node-fetch-native"; // or use global fetch
import { createProxy } from "node-fetch-native/proxy";
import { createFetch } from "node-fetch-native/proxy";

process.env.HTTPS_PROXY = "http://localhost:9080";
process.env.DEBUG = "true";
const fetch = createFetch({ url: "http://localhost:9080" });

const proxy = createProxy();

const res = await fetch("https://icanhazip.com", {
...proxy,
});

console.log(await res.text());
console.log(await fetch("https://icanhazip.com").then((r) => r.text()));
9 changes: 5 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Node",
"esModuleInterop": true
"esModuleInterop": true,
"paths": {
"node-fetch-native": ["."]
}
},
"include": [
"src"
]
"include": ["src"]
}

0 comments on commit b5ca4c3

Please sign in to comment.