Skip to content

Commit 966e9cc

Browse files
authored
Merge pull request #2609 from cdr/proxy-res-d629
Fix body proxying, redirect proxying and add tests
2 parents d7f0697 + a60f61f commit 966e9cc

File tree

4 files changed

+75
-16
lines changed

4 files changed

+75
-16
lines changed

src/node/proxy.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ proxy.on("error", (error, _, res) => {
99
})
1010

1111
// Intercept the response to rewrite absolute redirects against the base path.
12+
// Is disabled when the request has no base path which means --proxy-path-passthrough has
13+
// been enabled.
1214
proxy.on("proxyRes", (res, req) => {
1315
if (res.headers.location && res.headers.location.startsWith("/") && (req as any).base) {
1416
res.headers.location = (req as any).base + res.headers.location

src/node/routes/index.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ export const register = async (
6565
app.use(cookieParser())
6666
wsApp.use(cookieParser())
6767

68-
app.use(bodyParser.json())
69-
app.use(bodyParser.urlencoded({ extended: true }))
70-
7168
const common: express.RequestHandler = (req, _, next) => {
7269
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
7370
// it look like code-server is always in use.
@@ -106,6 +103,12 @@ export const register = async (
106103
app.use("/", domainProxy.router)
107104
wsApp.use("/", domainProxy.wsRouter.router)
108105

106+
app.use("/proxy", proxy.router)
107+
wsApp.use("/proxy", proxy.wsRouter.router)
108+
109+
app.use(bodyParser.json())
110+
app.use(bodyParser.urlencoded({ extended: true }))
111+
109112
app.use("/", vscode.router)
110113
wsApp.use("/", vscode.wsRouter.router)
111114
app.use("/vscode", vscode.router)
@@ -121,9 +124,6 @@ export const register = async (
121124
})
122125
}
123126

124-
app.use("/proxy", proxy.router)
125-
wsApp.use("/proxy", proxy.wsRouter.router)
126-
127127
app.use("/static", _static.router)
128128
app.use("/update", update.router)
129129

src/node/routes/pathProxy.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ router.all("/(:port)(/*)?", (req, res) => {
2828
throw new HttpError("Unauthorized", HttpCode.Unauthorized)
2929
}
3030

31-
// Absolute redirects need to be based on the subpath when rewriting.
32-
;(req as any).base = `${req.baseUrl}/${req.params.port}`
31+
if (!req.args["proxy-path-passthrough"]) {
32+
// Absolute redirects need to be based on the subpath when rewriting.
33+
;(req as any).base = `${req.baseUrl}/${req.params.port}`
34+
}
3335

3436
proxy.web(req, res, {
3537
ignorePath: true,

test/proxy.test.ts

+63-8
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,29 @@
1+
import bodyParser from "body-parser"
12
import * as express from "express"
23
import * as httpserver from "./httpserver"
34
import * as integration from "./integration"
45

56
describe("proxy", () => {
6-
let codeServer: httpserver.HttpServer | undefined
77
const nhooyrDevServer = new httpserver.HttpServer()
8+
let codeServer: httpserver.HttpServer | undefined
89
let proxyPath: string
10+
let e: express.Express
911

1012
beforeAll(async () => {
11-
const e = express.default()
12-
await nhooyrDevServer.listen(e)
13-
e.get("/wsup", (req, res) => {
14-
res.json("asher is the best")
13+
await nhooyrDevServer.listen((req, res) => {
14+
e(req, res)
1515
})
1616
proxyPath = `/proxy/${nhooyrDevServer.port()}/wsup`
17-
e.get(proxyPath, (req, res) => {
18-
res.json("joe is the best")
19-
})
2017
})
2118

2219
afterAll(async () => {
2320
await nhooyrDevServer.close()
2421
})
2522

23+
beforeEach(() => {
24+
e = express.default()
25+
})
26+
2627
afterEach(async () => {
2728
if (codeServer) {
2829
await codeServer.close()
@@ -31,6 +32,9 @@ describe("proxy", () => {
3132
})
3233

3334
it("should rewrite the base path", async () => {
35+
e.get("/wsup", (req, res) => {
36+
res.json("asher is the best")
37+
})
3438
;[, , codeServer] = await integration.setup(["--auth=none"], "")
3539
const resp = await codeServer.fetch(proxyPath)
3640
expect(resp.status).toBe(200)
@@ -39,10 +43,61 @@ describe("proxy", () => {
3943
})
4044

4145
it("should not rewrite the base path", async () => {
46+
e.get(proxyPath, (req, res) => {
47+
res.json("joe is the best")
48+
})
4249
;[, , codeServer] = await integration.setup(["--auth=none", "--proxy-path-passthrough=true"], "")
4350
const resp = await codeServer.fetch(proxyPath)
4451
expect(resp.status).toBe(200)
4552
const json = await resp.json()
4653
expect(json).toBe("joe is the best")
4754
})
55+
56+
it("should rewrite redirects", async () => {
57+
e.post("/wsup", (req, res) => {
58+
res.redirect(307, "/finale")
59+
})
60+
e.post("/finale", (req, res) => {
61+
res.json("redirect success")
62+
})
63+
;[, , codeServer] = await integration.setup(["--auth=none"], "")
64+
const resp = await codeServer.fetch(proxyPath, {
65+
method: "POST",
66+
})
67+
expect(resp.status).toBe(200)
68+
expect(await resp.json()).toBe("redirect success")
69+
})
70+
71+
it("should not rewrite redirects", async () => {
72+
const finalePath = proxyPath.replace("/wsup", "/finale")
73+
e.post(proxyPath, (req, res) => {
74+
res.redirect(307, finalePath)
75+
})
76+
e.post(finalePath, (req, res) => {
77+
res.json("redirect success")
78+
})
79+
;[, , codeServer] = await integration.setup(["--auth=none", "--proxy-path-passthrough=true"], "")
80+
const resp = await codeServer.fetch(proxyPath, {
81+
method: "POST",
82+
})
83+
expect(resp.status).toBe(200)
84+
expect(await resp.json()).toBe("redirect success")
85+
})
86+
87+
it("should allow post bodies", async () => {
88+
e.use(bodyParser.json({ strict: false }))
89+
e.post("/wsup", (req, res) => {
90+
res.json(req.body)
91+
})
92+
;[, , codeServer] = await integration.setup(["--auth=none"], "")
93+
const resp = await codeServer.fetch(proxyPath, {
94+
method: "post",
95+
body: JSON.stringify("coder is the best"),
96+
headers: {
97+
"Content-Type": "application/json",
98+
},
99+
})
100+
expect(resp.status).toBe(200)
101+
expect(await resp.json()).toBe("coder is the best")
102+
})
48103
})

0 commit comments

Comments
 (0)