From f8a4da7667f341be92d9cc71e3ce32cb72ee2ff4 Mon Sep 17 00:00:00 2001 From: rafael_ferreira Date: Sun, 25 Aug 2024 12:01:06 +0100 Subject: [PATCH 1/3] feat: introduce --abs-proxy-base-path that allows app proxying while code-server is not server at the root. --- docs/guide.md | 9 +++++++++ src/node/cli.ts | 29 +++++++++++++++++------------ src/node/routes/index.ts | 2 ++ src/node/routes/pathProxy.ts | 15 +++++++++++---- test/unit/node/cli.test.ts | 3 +++ test/unit/node/proxy.test.ts | 12 ++++++++++++ 6 files changed, 54 insertions(+), 16 deletions(-) diff --git a/docs/guide.md b/docs/guide.md index 6d164c694dea..0d0c131409db 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -432,3 +432,12 @@ const config = { 3. Access app at `/absproxy/5173/` e.g. `http://localhost:8080/absproxy/5173/ For additional context, see [this Github Issue](https://github.com/sveltejs/kit/issues/2958) + +### Prefixing `/absproxy/` with a path + +This is a case where you need to serve an application via `absproxy` as explained above while serving `codeserver` itself from a path other than the root in your domain. + +For example: `http://my-code-server.com/user/123/workspace/my-app`. To achieve this result: + +1. start code server with the switch `--abs-proxy-base-path=/user/123/workspace` +2. Follow one of the instructions above for your framework. diff --git a/src/node/cli.ts b/src/node/cli.ts index 69890279e396..36cb29e75d81 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -53,6 +53,7 @@ export interface UserProvidedCodeArgs { "disable-getting-started-override"?: boolean "disable-proxy"?: boolean "session-socket"?: string + "abs-proxy-base-path"?: string } /** @@ -117,18 +118,18 @@ interface Option { type OptionType = T extends boolean ? "boolean" : T extends OptionalString - ? typeof OptionalString - : T extends LogLevel - ? typeof LogLevel - : T extends AuthType - ? typeof AuthType - : T extends number - ? "number" - : T extends string - ? "string" - : T extends string[] - ? "string[]" - : "unknown" + ? typeof OptionalString + : T extends LogLevel + ? typeof LogLevel + : T extends AuthType + ? typeof AuthType + : T extends number + ? "number" + : T extends string + ? "string" + : T extends string[] + ? "string[]" + : "unknown" export type Options = { [P in keyof T]: Option> @@ -279,6 +280,10 @@ export const options: Options> = { short: "w", description: "Text to show on login page", }, + "abs-proxy-base-path": { + type: "string", + description: "The base path to prefix all absproxy requests", + }, } export const optionDescriptions = (opts: Partial>> = options): string[] => { diff --git a/src/node/routes/index.ts b/src/node/routes/index.ts index 1be3988ca3ad..e61cbd65795c 100644 --- a/src/node/routes/index.ts +++ b/src/node/routes/index.ts @@ -121,11 +121,13 @@ export const register = async (app: App, args: DefaultedArgs): Promise { await pathProxy.proxy(req, res, { passthroughPath: true, + proxyBasePath: args["abs-proxy-base-path"], }) }) app.wsRouter.get("/absproxy/:port/:path(.*)?", async (req) => { await pathProxy.wsProxy(req as pluginapi.WebsocketRequest, { passthroughPath: true, + proxyBasePath: args["abs-proxy-base-path"], }) }) diff --git a/src/node/routes/pathProxy.ts b/src/node/routes/pathProxy.ts index 7f69bcf9eb17..ccfb0cc824a0 100644 --- a/src/node/routes/pathProxy.ts +++ b/src/node/routes/pathProxy.ts @@ -5,10 +5,15 @@ import { HttpCode, HttpError } from "../../common/http" import { ensureProxyEnabled, authenticated, ensureAuthenticated, ensureOrigin, redirect, self } from "../http" import { proxy as _proxy } from "../proxy" -const getProxyTarget = (req: Request): string => { +const getProxyTarget = ( + req: Request, + opts?: { + proxyBasePath?: string + }, +): string => { // If there is a base path, strip it out. const base = (req as any).base || "" - return `http://0.0.0.0:${req.params.port}/${req.originalUrl.slice(base.length)}` + return `http://0.0.0.0:${req.params.port}${opts?.proxyBasePath || ""}/${req.originalUrl.slice(base.length)}` } export async function proxy( @@ -16,6 +21,7 @@ export async function proxy( res: Response, opts?: { passthroughPath?: boolean + proxyBasePath?: string }, ): Promise { ensureProxyEnabled(req) @@ -38,7 +44,7 @@ export async function proxy( _proxy.web(req, res, { ignorePath: true, - target: getProxyTarget(req), + target: getProxyTarget(req, opts), }) } @@ -46,6 +52,7 @@ export async function wsProxy( req: pluginapi.WebsocketRequest, opts?: { passthroughPath?: boolean + proxyBasePath?: string }, ): Promise { ensureProxyEnabled(req) @@ -59,6 +66,6 @@ export async function wsProxy( _proxy.ws(req, req.ws, req.head, { ignorePath: true, - target: getProxyTarget(req), + target: getProxyTarget(req, opts), }) } diff --git a/test/unit/node/cli.test.ts b/test/unit/node/cli.test.ts index 02b60b839efb..e596549da100 100644 --- a/test/unit/node/cli.test.ts +++ b/test/unit/node/cli.test.ts @@ -106,6 +106,8 @@ describe("parser", () => { "--disable-proxy", + ["--abs-proxy-base-path", "/codeserver/app1"], + ["--session-socket", "/tmp/override-code-server-ipc-socket"], ["--host", "0.0.0.0"], @@ -143,6 +145,7 @@ describe("parser", () => { version: true, "bind-addr": "192.169.0.1:8080", "session-socket": "/tmp/override-code-server-ipc-socket", + "abs-proxy-base-path": "/codeserver/app1", }) }) diff --git a/test/unit/node/proxy.test.ts b/test/unit/node/proxy.test.ts index 9e8017e37700..186cd475b3e2 100644 --- a/test/unit/node/proxy.test.ts +++ b/test/unit/node/proxy.test.ts @@ -256,6 +256,18 @@ describe("proxy", () => { expect(spy).toHaveBeenCalledWith([test.expected, test.query]) } }) + + it("should allow specifying an absproxy path", async () => { + const prefixedPath = `/codeserver/app1${absProxyPath}` + e.get(prefixedPath, (req, res) => { + res.send("app being served behind a prefixed path") + }) + codeServer = await integration.setup(["--auth=none", "--abs-proxy-base-path=/codeserver/app1"], "") + const resp = await codeServer.fetch(absProxyPath) + expect(resp.status).toBe(200) + const text = await resp.text() + expect(text).toBe("app being served behind a prefixed path") + }) }) // NOTE@jsjoeio From f74333cef387472b932fc4125d05e96a820b3bd8 Mon Sep 17 00:00:00 2001 From: Asher Date: Mon, 26 Aug 2024 11:31:52 -0800 Subject: [PATCH 2/3] Run formatter Not sure why it keeps trying to indent the options though, in CI it wants it flat. Going to keep it flat for now until we figure it out. --- docs/guide.md | 1 + src/node/cli.ts | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/guide.md b/docs/guide.md index 0d0c131409db..5f55e992641d 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -20,6 +20,7 @@ - [Proxying to a Vue app](#proxying-to-a-vue-app) - [Proxying to an Angular app](#proxying-to-an-angular-app) - [Proxying to a Svelte app](#proxying-to-a-svelte-app) + - [Prefixing `/absproxy/` with a path](#prefixing-absproxyport-with-a-path) diff --git a/src/node/cli.ts b/src/node/cli.ts index 36cb29e75d81..6320c2025239 100644 --- a/src/node/cli.ts +++ b/src/node/cli.ts @@ -118,18 +118,18 @@ interface Option { type OptionType = T extends boolean ? "boolean" : T extends OptionalString - ? typeof OptionalString - : T extends LogLevel - ? typeof LogLevel - : T extends AuthType - ? typeof AuthType - : T extends number - ? "number" - : T extends string - ? "string" - : T extends string[] - ? "string[]" - : "unknown" + ? typeof OptionalString + : T extends LogLevel + ? typeof LogLevel + : T extends AuthType + ? typeof AuthType + : T extends number + ? "number" + : T extends string + ? "string" + : T extends string[] + ? "string[]" + : "unknown" export type Options = { [P in keyof T]: Option> @@ -282,7 +282,7 @@ export const options: Options> = { }, "abs-proxy-base-path": { type: "string", - description: "The base path to prefix all absproxy requests", + description: "The base path to prefix to all absproxy requests", }, } From 71d10b1b13224d1cd2f9e9d2071c5d9a8053c1fa Mon Sep 17 00:00:00 2001 From: Asher Date: Mon, 26 Aug 2024 11:34:20 -0800 Subject: [PATCH 3/3] Capitalize --- docs/guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide.md b/docs/guide.md index 5f55e992641d..60098ca7e679 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -440,5 +440,5 @@ This is a case where you need to serve an application via `absproxy` as explaine For example: `http://my-code-server.com/user/123/workspace/my-app`. To achieve this result: -1. start code server with the switch `--abs-proxy-base-path=/user/123/workspace` +1. Start code server with the switch `--abs-proxy-base-path=/user/123/workspace` 2. Follow one of the instructions above for your framework.