Skip to content

Commit b5ca4c3

Browse files
authored
feat(proxy): export fetch and createFetch (#108)
1 parent 16f01ce commit b5ca4c3

11 files changed

+87
-58
lines changed

README.md

+36-20
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ You have two ways to do this:
9393

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

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

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

110110
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))
111111

112-
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).
112+
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).
113113

114-
**Usage:**
114+
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.
115+
116+
> [!NOTE]
117+
> Using export conditions, this utility adds proxy support for Node.js and for other runtimes, it will simply return native fetch.
118+
119+
> [!IMPORTANT]
120+
> 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!
121+
122+
### `fetch` with proxy support
123+
124+
You can simply import `{ fetch }` from `node-fetch-native/proxy` with a preconfigured `fetch` function that has proxy support.
115125

116126
```ts
117-
import { fetch } from "node-fetch-native"; // or use global fetch
118-
import { createProxy } from "node-fetch-native/proxy";
127+
import { fetch } from "node-fetch-native/proxy";
119128

120-
// Uses HTTPS_PROXY or HTTP_PROXY environment variables
121-
const proxy = createProxy();
129+
console.log(await fetch("https://icanhazip.com").then((r) => r.text());
130+
```
122131
123-
// const proxy = createProxy({ url: "http://localhost:8080" });
132+
### `createFetch` utility
133+
134+
You can use `createFetch` utility to intantiate a `fetch` instance with custom proxy options.
135+
136+
```ts
137+
import { createFetch } from "node-fetch-native/proxy";
138+
139+
const fetch = createFetch({ url: "http://localhost:9080" });
124140

125-
await fetch("https://google.com", {
126-
...proxy,
127-
});
141+
console.log(await fetch("https://icanhazip.com").then((r) => r.text());
128142
```
129143
130-
`createProxy` returns an object with `agent` for older Node.js versions and `dispatcher` keys for newer Node.js versions with Undici and native fetch.
144+
### `createProxy` utility
131145
132-
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.
146+
`createProxy` returns an object with `agent` and `dispatcher` keys that can be passed as fetch options.
133147
134-
> [!NOTE]
135-
> 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!
148+
```ts
149+
import { fetch } from "node-fetch-native";
150+
import { createProxy } from "node-fetch-native/proxy";
136151

137-
> [!NOTE]
138-
> 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!
152+
const proxy = createProxy();
153+
// const proxy = createProxy({ url: "http://localhost:8080" });
154+
155+
console.log(await fetch("https://icanhazip.com", { ...proxy }).then((r) => r.text());
156+
```
139157
140158
## Alias to `node-fetch`
141159
@@ -184,9 +202,7 @@ Using [pnpm.overrides](https://pnpm.io/package_json#pnpmoverrides):
184202
185203
## License
186204
187-
Made with 💛
188-
189-
[node-fetch is published under the MIT license](https://github.com/node-fetch/node-fetch/blob/main/LICENSE.md)
205+
Made with 💛 Published under the [MIT](./LICENSE) license.
190206
191207
<!-- Badges -->
192208

build.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default defineBuildConfig({
2323
"src/proxy",
2424
"src/proxy-stub",
2525
],
26+
externals: ["node-fetch-native"],
2627
hooks: {
2728
async "build:done"(ctx) {
2829
// Save few bytes from dist...

lib/proxy.d.cts

-8
This file was deleted.

lib/proxy.d.mts

-8
This file was deleted.

lib/proxy.d.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type * as http from "node:http";
2+
import type * as https from "node:https";
3+
import type * as undici from "undici";
4+
5+
export type ProxyOptions = { url?: string };
6+
7+
export declare const createProxy: (opts?: ProxyOptions) => {
8+
agent: http.Agent | https.Agent | undefined;
9+
dispatcher: undici.Dispatcher | undefined;
10+
};
11+
12+
export declare const createFetch: (
13+
proxyOptions?: ProxyOptions,
14+
) => typeof globalThis.fetch;
15+
16+
export declare const fetch: typeof globalThis.fetch;

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -82,21 +82,21 @@
8282
"./proxy": {
8383
"node": {
8484
"import": {
85-
"types": "./lib/proxy.d.mts",
85+
"types": "./lib/proxy.d.ts",
8686
"default": "./dist/proxy.cjs"
8787
},
8888
"require": {
89-
"types": "./lib/proxy.d.cts",
89+
"types": "./lib/proxy.d.ts",
9090
"default": "./dist/proxy.cjs"
9191
}
9292
},
9393
"default": {
9494
"import": {
95-
"types": "./lib/proxy.d.mts",
95+
"types": "./lib/proxy.d.ts",
9696
"default": "./dist/proxy-stub.mjs"
9797
},
9898
"require": {
99-
"types": "./lib/proxy.d.cts",
99+
"types": "./lib/proxy.d.ts",
100100
"default": "./dist/proxy-stub.cjs"
101101
}
102102
}
@@ -141,4 +141,4 @@
141141
"vitest": "^1.1.0"
142142
},
143143
"packageManager": "pnpm@8.12.1"
144-
}
144+
}

proxy.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from "./lib/proxy.mjs";
1+
export * from "./lib/proxy";

src/proxy-stub.ts

+6
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,9 @@ export function createProxy() {
44
dispatcher: undefined,
55
};
66
}
7+
8+
export function createFetch() {
9+
return globalThis.fetch;
10+
}
11+
12+
export const fetch = globalThis.fetch;

src/proxy.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import { ProxyAgent as UndiciProxyAgent } from "undici";
55
import { Agent, AgentConnectOpts } from "agent-base";
66
import { HttpProxyAgent } from "http-proxy-agent";
77
import { HttpsProxyAgent } from "https-proxy-agent";
8+
import type { ProxyOptions } from "../proxy";
9+
import { fetch as _fetch } from "node-fetch-native";
810

9-
export function createProxy(opts: { url?: string } = {}) {
11+
export function createProxy(opts: ProxyOptions = {}) {
1012
const uri =
1113
opts.url ||
1214
process.env.HTTPS_PROXY ||
@@ -32,6 +34,17 @@ export function createProxy(opts: { url?: string } = {}) {
3234
};
3335
}
3436

37+
export function createFetch(proxyOptions: ProxyOptions = {}) {
38+
const proxy = createProxy(proxyOptions);
39+
return (url, fetchOptions) => _fetch(url, { ...proxy, ...fetchOptions });
40+
}
41+
42+
export const fetch = createFetch({});
43+
44+
// ----------------------------------------------
45+
// Utils
46+
// ----------------------------------------------
47+
3548
export function debug(...args: any[]) {
3649
if (process.env.debug) {
3750
debug("[node-fetch-native] [proxy]", ...args);

test/proxy.mjs

+3-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
1-
import { fetch } from "node-fetch-native"; // or use global fetch
2-
import { createProxy } from "node-fetch-native/proxy";
1+
import { createFetch } from "node-fetch-native/proxy";
32

4-
process.env.HTTPS_PROXY = "http://localhost:9080";
5-
process.env.DEBUG = "true";
3+
const fetch = createFetch({ url: "http://localhost:9080" });
64

7-
const proxy = createProxy();
8-
9-
const res = await fetch("https://icanhazip.com", {
10-
...proxy,
11-
});
12-
13-
console.log(await res.text());
5+
console.log(await fetch("https://icanhazip.com").then((r) => r.text()));

tsconfig.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
"target": "ESNext",
44
"module": "ESNext",
55
"moduleResolution": "Node",
6-
"esModuleInterop": true
6+
"esModuleInterop": true,
7+
"paths": {
8+
"node-fetch-native": ["."]
9+
}
710
},
8-
"include": [
9-
"src"
10-
]
11+
"include": ["src"]
1112
}

0 commit comments

Comments
 (0)