11import { logger } from "@coder/logger"
22import * as http from "http"
3- import * as url from "url "
4- import * as proxyagent from "proxy-agent "
3+ import * as proxyAgent from "proxy-agent "
4+ import * as proxyFromEnv from "proxy-from-env "
55
66/**
77 * This file has nothing to do with the code-server proxy.
8- * It is for $HTTP_PROXY and $HTTPS_PROXY support.
8+ * It is to support $HTTP_PROXY, $HTTPS_PROXY and $NO_PROXY.
9+ *
910 * - https://github.com/cdr/code-server/issues/124
1011 * - https://www.npmjs.com/package/proxy-agent
12+ * - https://www.npmjs.com/package/proxy-from-env
1113 *
1214 * This file exists in two locations:
1315 * - src/node/proxy_agent.ts
@@ -17,7 +19,7 @@ import * as proxyagent from "proxy-agent"
1719
1820/**
1921 * monkeyPatch patches the node http,https modules to route all requests through the
20- * agents we get from the proxy-agent package.
22+ * agent we get from the proxy-agent package.
2123 *
2224 * This approach only works if there is no code specifying an explicit agent when making
2325 * a request.
@@ -28,29 +30,22 @@ import * as proxyagent from "proxy-agent"
2830 *
2931 * Even if they do, it's probably the same proxy so we should be fine! And those knobs
3032 * are deprecated anyway.
31- *
32- * We use $HTTP_PROXY for all HTTP resources via a normal HTTP proxy.
33- * We use $HTTPS_PROXY for all HTTPS resources via HTTP connect.
34- * See https://stackoverflow.com/a/10442767/4283659
3533 */
3634export function monkeyPatch ( inVSCode : boolean ) : void {
37- const http = require ( "http" )
38- const https = require ( "https" )
39-
40- const httpProxyURL = process . env . HTTP_PROXY || process . env . http_proxy
41- if ( httpProxyURL ) {
42- logger . debug ( `using $HTTP_PROXY ${ httpProxyURL } ` )
43- http . globalAgent = newProxyAgent ( inVSCode , httpProxyURL )
44- }
35+ if ( shouldEnableProxy ( ) ) {
36+ const http = require ( "http" )
37+ const https = require ( "https" )
4538
46- const httpsProxyURL = process . env . HTTPS_PROXY || process . env . https_proxy
47- if ( httpsProxyURL ) {
48- logger . debug ( `using $HTTPS_PROXY ${ httpsProxyURL } ` )
49- https . globalAgent = newProxyAgent ( inVSCode , httpsProxyURL )
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
5045 }
5146}
5247
53- function newProxyAgent ( inVSCode : boolean , for : "http" | "https" , proxyURL : string ) : http . Agent {
48+ function newProxyAgent ( inVSCode : boolean ) : http . Agent {
5449 // The reasoning for this split is that VS Code's build process does not have
5550 // esModuleInterop enabled but the code-server one does. As a result depending on where
5651 // we execute, we either have a default attribute or we don't.
@@ -59,8 +54,28 @@ function newProxyAgent(inVSCode: boolean, for: "http" | "https", proxyURL: strin
5954 // a huge number of errors. And we can't use require as otherwise the modules won't be
6055 // included in the final product.
6156 if ( inVSCode ) {
62- return new ( proxyagent as any ) ( opts )
57+ return new ( proxyAgent as any ) ( )
6358 } else {
64- return new ( proxyagent as any ) . default ( opts )
59+ return new ( proxyAgent as any ) . default ( )
6560 }
6661}
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 } ` )
78+ }
79+
80+ return shouldEnable
81+ }
0 commit comments