diff --git a/src/cli.ts b/src/cli.ts index 8e0dcc59..fe686190 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -15,6 +15,7 @@ import { generateCertificate, generatePassword, open, unpackExecutables } from " interface Args extends ParsedArgs { "allow-http"?: boolean; auth?: boolean; + "base-path"?: string; cert?: string; "cert-key"?: string; "extra-builtin-extensions-dir"?: string; @@ -54,6 +55,7 @@ while (i--) { } options.push({ id: "allow-http", type: "boolean", cat: "o", description: "Allow http connections." }); +options.push({ id: "base-path", type: "string", cat: "o", description: "Base path of the URL at which code-server is hosted (used for login redirects)." }); options.push({ id: "cert", type: "string", cat: "o", description: "Path to certificate." }); options.push({ id: "cert-key", type: "string", cat: "o", description: "Path to certificate key." }); options.push({ id: "extra-builtin-extensions-dir", type: "string", cat: "o", description: "Path to extra builtin extension directory." }); @@ -118,6 +120,7 @@ const main = async (): Promise => { const options = { allowHttp: args["allow-http"], auth: typeof args.auth !== "undefined" ? args.auth : true, + basePath: args["base-path"], cert: args.cert, certKey: args["cert-key"], folderUri: extra.length > 1 ? extra[extra.length - 1] : undefined, diff --git a/src/server.ts b/src/server.ts index 9d44a1ca..81af75cf 100644 --- a/src/server.ts +++ b/src/server.ts @@ -96,15 +96,16 @@ export class HttpError extends Error { } export interface ServerOptions { - readonly port?: number; - readonly host?: string; - readonly socket?: string; readonly allowHttp?: boolean; + readonly auth?: boolean; + readonly basePath?: string; readonly cert?: string; readonly certKey?: string; - readonly auth?: boolean; - readonly password?: string; readonly folderUri?: string; + readonly host?: string; + readonly password?: string; + readonly port?: number; + readonly socket?: string; } export abstract class Server { @@ -112,9 +113,13 @@ export abstract class Server { protected rootPath = path.resolve(__dirname, "../../../.."); private listenPromise: Promise | undefined; private readonly protocol: string; + private readonly basePath: string = ""; public constructor(public readonly options: ServerOptions) { this.protocol = this.options.allowHttp ? "http" : "https"; + if (this.options.basePath) { + this.basePath = this.options.basePath.replace(/\/+$/, ""); + } if (this.options.cert && this.options.certKey) { const httpolyglot = require.__$__nodeRequire(path.resolve(__dirname, "../node_modules/httpolyglot/lib/index")) as typeof import("httpolyglot"); this.server = httpolyglot.createServer({ @@ -175,7 +180,7 @@ export abstract class Server { "Cache-Control": "max-age=86400", // TODO: ETag? "Content-Type": getMediaMime(payload.filePath), ...(payload.redirect ? { - Location: `${this.protocol}://${request.headers.host}${payload.redirect}`, + Location: `${this.protocol}://${request.headers.host}${this.basePath}${payload.redirect}`, } : {}), ...payload.headers, });