Skip to content

Commit eac65ca

Browse files
authored
Merge pull request #92 from lroolle/feat/proxy-dispatch-no-proxy-logs
proxy: respect env proxy via undici
2 parents 573a90c + 17fe0a6 commit eac65ca

File tree

4 files changed

+78
-5
lines changed

4 files changed

+78
-5
lines changed

bun.lock

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
"consola": "^3.4.2",
1010
"fetch-event-stream": "^0.1.5",
1111
"gpt-tokenizer": "^3.0.1",
12-
"hono": "^4.9.6",
13-
"srvx": "^0.8.7",
12+
"hono": "^4.9.4",
13+
"proxy-from-env": "^1.1.0",
14+
"srvx": "^0.8.6",
1415
"tiny-invariant": "^1.3.3",
16+
"undici": "^6.19.8",
1517
},
1618
"devDependencies": {
1719
"@echristian/eslint-config": "^0.0.54",
@@ -762,6 +764,8 @@
762764

763765
"prettier-plugin-packagejson": ["prettier-plugin-packagejson@2.5.19", "", { "dependencies": { "sort-package-json": "3.4.0", "synckit": "0.11.11" }, "peerDependencies": { "prettier": ">= 1.16.0" }, "optionalPeers": ["prettier"] }, "sha512-Qsqp4+jsZbKMpEGZB1UP1pxeAT8sCzne2IwnKkr+QhUe665EXUo3BAvTf1kAPCqyMv9kg3ZmO0+7eOni/C6Uag=="],
764766

767+
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
768+
765769
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
766770

767771
"quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="],
@@ -918,6 +922,8 @@
918922

919923
"unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="],
920924

925+
"undici": ["undici@6.21.3", "", {}, "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw=="],
926+
921927
"undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
922928

923929
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@
4444
"consola": "^3.4.2",
4545
"fetch-event-stream": "^0.1.5",
4646
"gpt-tokenizer": "^3.0.1",
47-
"hono": "^4.9.6",
48-
"srvx": "^0.8.7",
49-
"tiny-invariant": "^1.3.3"
47+
"hono": "^4.9.4",
48+
"proxy-from-env": "^1.1.0",
49+
"srvx": "^0.8.6",
50+
"tiny-invariant": "^1.3.3",
51+
"undici": "^6.19.8"
5052
},
5153
"devDependencies": {
5254
"@echristian/eslint-config": "^0.0.54",

src/lib/proxy.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import consola from "consola"
2+
import { getProxyForUrl } from "proxy-from-env"
3+
import { Agent, ProxyAgent, setGlobalDispatcher, type Dispatcher } from "undici"
4+
5+
export function initProxyFromEnv(): void {
6+
if (typeof Bun !== "undefined") return
7+
8+
try {
9+
const direct = new Agent()
10+
const proxies = new Map<string, ProxyAgent>()
11+
12+
const dispatcher: Dispatcher = {
13+
dispatch(
14+
options: Dispatcher.RequestOptions,
15+
handler: Dispatcher.DispatchHandlers,
16+
) {
17+
try {
18+
const origin =
19+
typeof options.origin === "string" ?
20+
new URL(options.origin)
21+
: (options.origin as URL)
22+
const get = getProxyForUrl as unknown as (
23+
u: string,
24+
) => string | undefined
25+
const raw = get(origin.toString())
26+
const proxyUrl = raw && raw.length > 0 ? raw : undefined
27+
if (!proxyUrl) {
28+
consola.debug(`HTTP proxy bypass: ${origin.hostname}`)
29+
return (direct as unknown as Dispatcher).dispatch(options, handler)
30+
}
31+
let agent = proxies.get(proxyUrl)
32+
if (!agent) {
33+
agent = new ProxyAgent(proxyUrl)
34+
proxies.set(proxyUrl, agent)
35+
}
36+
let label = proxyUrl
37+
try {
38+
const u = new URL(proxyUrl)
39+
label = `${u.protocol}//${u.host}`
40+
} catch {
41+
/* noop */
42+
}
43+
consola.debug(`HTTP proxy route: ${origin.hostname} via ${label}`)
44+
return (agent as unknown as Dispatcher).dispatch(options, handler)
45+
} catch {
46+
return (direct as unknown as Dispatcher).dispatch(options, handler)
47+
}
48+
},
49+
close() {
50+
return direct.close()
51+
},
52+
destroy() {
53+
return direct.destroy()
54+
},
55+
}
56+
57+
setGlobalDispatcher(dispatcher)
58+
consola.debug("HTTP proxy configured from environment (per-URL)")
59+
} catch (err) {
60+
consola.debug("Proxy setup skipped:", err)
61+
}
62+
}

src/main.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { defineCommand, runMain } from "citty"
55
import { auth } from "./auth"
66
import { checkUsage } from "./check-usage"
77
import { debug } from "./debug"
8+
import { initProxyFromEnv } from "./lib/proxy"
89
import { start } from "./start"
910

1011
const main = defineCommand({
@@ -16,4 +17,6 @@ const main = defineCommand({
1617
subCommands: { auth, start, "check-usage": checkUsage, debug },
1718
})
1819

20+
initProxyFromEnv()
21+
1922
await runMain(main)

0 commit comments

Comments
 (0)