Skip to content

Commit eb4864f

Browse files
authored
Merge pull request #2400 from cdr/HTTP_PROXY-7e1f
Use proxy-agent to support $HTTP_PROXY
2 parents 366d182 + 58bbf25 commit eb4864f

File tree

8 files changed

+891
-32
lines changed

8 files changed

+891
-32
lines changed

ci/dev/lint.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ main() {
1414

1515
cd lib/vscode
1616
# Run this periodically in vanilla VS code to make sure we don't add any more warnings.
17-
yarn eslint --max-warnings=3
17+
yarn -s eslint --max-warnings=3
1818
cd "$OLDPWD"
1919
}
2020

ci/dev/vscode.patch

+589-27
Large diffs are not rendered by default.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"js-yaml": "^3.13.1",
8383
"limiter": "^1.1.5",
8484
"pem": "^1.14.2",
85+
"proxy-agent": "^4.0.0",
8586
"qs": "6.7.0",
8687
"rotating-file-stream": "^2.1.1",
8788
"safe-buffer": "^5.1.1",
File renamed without changes.

src/node/entry.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ import {
1515
shouldOpenInExistingInstance,
1616
shouldRunVsCodeCli,
1717
} from "./cli"
18-
import { coderCloudBind } from "./coder-cloud"
18+
import { coderCloudBind } from "./coder_cloud"
1919
import { commit, version } from "./constants"
20+
import * as proxyAgent from "./proxy_agent"
2021
import { register } from "./routes"
2122
import { humanPath, isFile, open } from "./util"
2223
import { isChild, wrapper } from "./wrapper"
@@ -154,6 +155,8 @@ const main = async (args: DefaultedArgs): Promise<void> => {
154155
}
155156

156157
async function entry(): Promise<void> {
158+
proxyAgent.monkeyPatch(false)
159+
157160
// There's no need to check flags like --help or to spawn in an existing
158161
// instance for the child process because these would have already happened in
159162
// the parent and the child wouldn't have been spawned. We also get the

src/node/proxy_agent.ts

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { logger } from "@coder/logger"
2+
import * as http from "http"
3+
import * as proxyagent from "proxy-agent"
4+
5+
/**
6+
* This file does not have anything to do with the code-server proxy.
7+
* It's for $HTTP_PROXY support!
8+
* - https://github.com/cdr/code-server/issues/124
9+
* - https://www.npmjs.com/package/proxy-agent
10+
*
11+
* This file exists in two locations:
12+
* - src/node/proxy_agent.ts
13+
* - lib/vscode/src/vs/base/node/proxy_agent.ts
14+
* The second is a symlink to the first.
15+
*/
16+
17+
/**
18+
* monkeyPatch patches the node HTTP/HTTPS library to route all requests through our
19+
* custom agent from the proxyAgent package.
20+
*/
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+
35+
logger.debug(`using $HTTP_PROXY ${process.env.HTTP_PROXY}`)
36+
37+
let pa: http.Agent
38+
// The reasoning for this split is that VS Code's build process does not have
39+
// esModuleInterop enabled but the code-server one does. As a result depending on where
40+
// we execute, we either have a default attribute or we don't.
41+
//
42+
// 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)
46+
} else {
47+
pa = new (proxyagent as any).default(process.env.HTTP_PROXY)
48+
}
49+
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
62+
}

src/node/update.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,13 @@ export class UpdateProvider {
106106
const httpx = uri.startsWith("https") ? https : http
107107
const client = httpx.get(uri, { headers: { "User-Agent": "code-server" } }, (response) => {
108108
if (!response.statusCode || response.statusCode < 200 || response.statusCode >= 400) {
109+
response.destroy()
109110
return reject(new Error(`${uri}: ${response.statusCode || "500"}`))
110111
}
111112

112113
if (response.statusCode >= 300) {
113-
++redirects
114114
response.destroy()
115+
++redirects
115116
if (redirects > maxRedirects) {
116117
return reject(new Error("reached max redirects"))
117118
}

0 commit comments

Comments
 (0)