11import { logger } from "@coder/logger"
22import * as http from "http"
3- import * as proxyagent from "proxy-agent"
3+ import * as proxyAgent from "proxy-agent"
4+ import * as proxyFromEnv from "proxy-from-env"
45
56/**
6- * This file does not have anything to do with the code-server proxy.
7- * It's for $HTTP_PROXY support!
7+ * This file has nothing to do with the code-server proxy.
8+ * It is to support $HTTP_PROXY, $HTTPS_PROXY and $NO_PROXY.
9+ *
810 * - https://github.com/cdr/code-server/issues/124
911 * - https://www.npmjs.com/package/proxy-agent
12+ * - https://www.npmjs.com/package/proxy-from-env
1013 *
1114 * This file exists in two locations:
1215 * - src/node/proxy_agent.ts
@@ -15,48 +18,64 @@ import * as proxyagent from "proxy-agent"
1518 */
1619
1720/**
18- * monkeyPatch patches the node HTTP/HTTPS library to route all requests through our
19- * custom agent from the proxyAgent package.
21+ * monkeyPatch patches the node http,https modules to route all requests through the
22+ * agent we get from the proxy-agent package.
23+ *
24+ * This approach only works if there is no code specifying an explicit agent when making
25+ * a request.
26+ *
27+ * None of our code ever passes in a explicit agent to the http,https modules.
28+ * VS Code's does sometimes but only when a user sets the http.proxy configuration.
29+ * See https://code.visualstudio.com/docs/setup/network#_legacy-proxy-server-support
30+ *
31+ * Even if they do, it's probably the same proxy so we should be fine! And those knobs
32+ * are deprecated anyway.
2033 */
21- export function monkeyPatch ( vscode : boolean ) : void {
22- // We do not support HTTPS_PROXY here to avoid confusion. proxy-agent will automatically
23- // use the correct protocol to connect to the proxy depending on the requested URL.
24- //
25- // We could implement support ourselves to allow people to configure the proxy used for
26- // HTTPS vs HTTP but there doesn't seem to be much value in that.
27- //
28- // At least of right now, it'd just be plain confusing to support HTTPS_PROXY when proxy-agent
29- // will still use HTTP to hit it for HTTP requests.
30- const proxyURL = process . env . HTTP_PROXY || process . env . http_proxy
31- if ( ! proxyURL ) {
32- return
33- }
34+ export function monkeyPatch ( inVSCode : boolean ) : void {
35+ if ( shouldEnableProxy ( ) ) {
36+ const http = require ( "http" )
37+ const https = require ( "https" )
3438
35- logger . debug ( `using $HTTP_PROXY ${ process . env . HTTP_PROXY } ` )
39+ // If we do not pass in a proxy URL, proxy-agent will get the URL from the environment.
40+ // See https://www.npmjs.com/package/proxy-from-env.
41+ // Also see shouldEnableProxy.
42+ const pa = newProxyAgent ( inVSCode )
43+ http . globalAgent = pa
44+ https . globalAgent = pa
45+ }
46+ }
3647
37- let pa : http . Agent
48+ function newProxyAgent ( inVSCode : boolean ) : http . Agent {
3849 // The reasoning for this split is that VS Code's build process does not have
3950 // esModuleInterop enabled but the code-server one does. As a result depending on where
4051 // we execute, we either have a default attribute or we don't.
4152 //
4253 // I can't enable esModuleInterop in VS Code's build process as it breaks and spits out
43- // a huge number of errors.
44- if ( vscode ) {
45- pa = new ( proxyagent as any ) ( process . env . HTTP_PROXY )
54+ // a huge number of errors. And we can't use require as otherwise the modules won't be
55+ // included in the final product.
56+ if ( inVSCode ) {
57+ return new ( proxyAgent as any ) ( )
4658 } else {
47- pa = new ( proxyagent as any ) . default ( process . env . HTTP_PROXY )
59+ return new ( proxyAgent as any ) . default ( )
60+ }
61+ }
62+
63+ // If they have $NO_PROXY set to example.com then this check won't work!
64+ // But that's drastically unlikely.
65+ function shouldEnableProxy ( ) : boolean {
66+ let shouldEnable = false
67+
68+ const httpProxy = proxyFromEnv . getProxyForUrl ( `http://example.com` )
69+ if ( httpProxy ) {
70+ shouldEnable = true
71+ logger . debug ( `using $HTTP_PROXY ${ httpProxy } ` )
72+ }
73+
74+ const httpsProxy = proxyFromEnv . getProxyForUrl ( `https://example.com` )
75+ if ( httpsProxy ) {
76+ shouldEnable = true
77+ logger . debug ( `using $HTTPS_PROXY ${ httpsProxy } ` )
4878 }
4979
50- /**
51- * None of our code ever passes in a explicit agent to the http modules but VS Code's
52- * does sometimes but only when a user sets the http.proxy configuration.
53- * See https://code.visualstudio.com/docs/setup/network#_legacy-proxy-server-support
54- *
55- * Even if they do, it's probably the same proxy so we should be fine! And those are
56- * deprecated anyway.
57- */
58- const http = require ( "http" )
59- const https = require ( "https" )
60- http . globalAgent = pa
61- https . globalAgent = pa
80+ return shouldEnable
6281}
0 commit comments