Skip to content

Commit c2e743e

Browse files
committed
use proxy-domain for everything
1 parent 5c63058 commit c2e743e

File tree

4 files changed

+52
-50
lines changed

4 files changed

+52
-50
lines changed

src/node/cli.ts

+16-4
Original file line numberDiff line numberDiff line change
@@ -573,11 +573,23 @@ export async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Config
573573
delete process.env.GITHUB_TOKEN
574574

575575
// Filter duplicate proxy domains and remove any leading `*.`.
576-
const proxyDomains = new Set((args["proxy-domain"] || []).map((d) => d.replace(/^\*\./, "")))
577-
args["proxy-domain"] = Array.from(proxyDomains)
578-
if (args["proxy-domain"].length > 0 && !process.env.VSCODE_PROXY_URI) {
579-
process.env.VSCODE_PROXY_URI = `{{port}}.${args["proxy-domain"][0]}`
576+
const proxyDomains = new Set((args["proxy-domain"] || []).map((d) => d.replace(/^\*\./, "")));
577+
let finalProxies = [];
578+
579+
for(let proxyDomain of proxyDomains) {
580+
if (!proxyDomain.includes("{{port}}")) {
581+
finalProxies.push("{{port}}." + proxyDomain);
582+
} else {
583+
finalProxies.push(proxyDomain);
584+
}
585+
}
586+
587+
// all proxies are of format anyprefix-{{port}}-anysuffix.{{host}}, where {{host}} is optional
588+
// e.g. code-8080.domain.tld would match for code-{{port}}.domain.tld and code-{{port}}.{{host}}
589+
if (finalProxies.length > 0 && !process.env.VSCODE_PROXY_URI) {
590+
process.env.VSCODE_PROXY_URI = `//${finalProxies[0]}`;
580591
}
592+
args["proxy-domain"] = finalProxies
581593

582594
if (typeof args._ === "undefined") {
583595
args._ = []

src/node/http.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ export function authenticateOrigin(req: express.Request): void {
373373
/**
374374
* Get the host from headers. It will be trimmed and lowercased.
375375
*/
376-
function getHost(req: express.Request): string | undefined {
376+
export function getHost(req: express.Request): string | undefined {
377377
// Honor Forwarded if present.
378378
const forwardedRaw = getFirstHeader(req, "forwarded")
379379
if (forwardedRaw) {

src/node/main.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,10 @@ export const runCodeServer = async (
149149

150150
if (args["proxy-domain"].length > 0) {
151151
logger.info(` - ${plural(args["proxy-domain"].length, "Proxying the following domain")}:`)
152-
args["proxy-domain"].forEach((domain) => logger.info(` - *.${domain}`))
152+
args["proxy-domain"].forEach((domain) => logger.info(` - ${domain}`))
153+
}
154+
if(process.env.VSCODE_PROXY_URI) {
155+
logger.info(`using proxy uri in PORTS tab: ${process.env.VSCODE_PROXY_URI}`)
153156
}
154157

155158
if (args.enable && args.enable.length > 0) {

src/node/routes/domainProxy.ts

+31-44
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,32 @@
11
import { Request, Router } from "express"
22
import { HttpCode, HttpError } from "../../common/http"
3+
import { getHost } from "../http"
34
import { authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http"
45
import { proxy } from "../proxy"
56
import { Router as WsRouter } from "../wsRouter"
67

78
export const router = Router()
89

10+
const proxyDomainToRegex = (matchString: string): RegExp => {
11+
let escapedMatchString = matchString.replace(/[.*+?^$()|[\]\\]/g, "\\$&");
12+
13+
// Replace {{port}} with a regex group to capture the port
14+
// Replace {{host}} with .+ to allow any host match (so rely on DNS record here)
15+
let regexString = escapedMatchString.replace("{{port}}", "(\\d+)");
16+
regexString = regexString.replace("{{host}}", ".+");
17+
18+
regexString = regexString.replace(/[{}]/g, "\\$&"); //replace any '{}' that might be left
19+
20+
return new RegExp("^" + regexString + "$");
21+
}
22+
23+
let proxyRegexes : RegExp[] = [];
24+
const proxyDomainsToRegex = (proxyDomains : string[]): RegExp[] => {
25+
if(proxyDomains.length != proxyRegexes.length) {
26+
proxyRegexes = proxyDomains.map(proxyDomainToRegex);
27+
}
28+
return proxyRegexes;
29+
}
930

1031
/**
1132
* Return the port if the request should be proxied. Anything that ends in a
@@ -16,56 +37,22 @@ export const router = Router()
1637
* but `8080.test.coder.com` and `test.8080.coder.com` will not.
1738
*/
1839
const maybeProxy = (req: Request): string | undefined => {
19-
// Split into parts.
20-
const host = req.headers.host || ""
21-
const idx = host.indexOf(":")
22-
const domain = idx !== -1 ? host.substring(0, idx) : host
23-
const parts = domain.split(".")
24-
25-
// There must be an exact match for proxy-domain
26-
const port = parts.shift()
27-
const proxyDomain = parts.join(".")
28-
if (port && req.args["proxy-domain"].includes(proxyDomain)) {
29-
return port
30-
}
31-
32-
// check based on VSCODE_PROXY_URI
33-
const proxyTemplate = process.env.VSCODE_PROXY_URI
34-
if(proxyTemplate) {
35-
return matchVsCodeProxyUriAndExtractPort(proxyTemplate, domain)
40+
let reqDomain = getHost(req);
41+
if (reqDomain === undefined) {
42+
return undefined;
3643
}
37-
38-
return undefined
39-
}
40-
41-
42-
let regex : RegExp | undefined = undefined;
43-
const matchVsCodeProxyUriAndExtractPort = (matchString: string, domain: string): string | undefined => {
44-
// init regex on first use
45-
if(!regex) {
46-
// Escape dot characters in the match string
47-
let escapedMatchString = matchString.replace(/\./g, "\\.");
48-
49-
// Replace {{port}} with a regex group to capture the port
50-
let regexString = escapedMatchString.replace("{{port}}", "(\\d+)");
5144

52-
// remove http:// and https:// from matchString as protocol cannot be determined based on the Host header
53-
regexString = regexString.replace("https://", "").replace("http://", "");
45+
let regexs = proxyDomainsToRegex(req.args["proxy-domain"]);
5446

55-
// Replace {{host}} with .* to allow any host match (so rely on DNS record here)
56-
regexString = regexString.replace("{{host}}", ".*");
47+
for(let regex of regexs){
48+
let match = reqDomain.match(regex);
5749

58-
regex = new RegExp("^" + regexString + "$");
59-
}
60-
61-
// Test the domain against the regex
62-
let match = domain.match(regex);
63-
64-
if (match) {
65-
return match[1]; // match[1] contains the port
50+
if (match) {
51+
return match[1]; // match[1] contains the port
52+
}
6653
}
6754

68-
return undefined;
55+
return undefined
6956
}
7057

7158
router.all("*", async (req, res, next) => {

0 commit comments

Comments
 (0)