mirror of
https://github.com/coder/code-server.git
synced 2026-06-16 15:07:11 +02:00
* Strip token from cookies before proxying Since this functionality requires information placed onto the request by code-server (req.args) and Express (req.cookies), move the standalone tests into the integration tests as the proxy can no longer run correctly on its own without that context. We could strip the header elsewhere or refactor in some way (pass in a callback function for the stripping or something) but this seems like the simplest and safest place at the moment to ensure we catch all uses of the proxy. In any case, I think it does lend more confidence to know we are testing the proxy the way it will be used in practice. The downside is some additional complexity when setting up tests, but at the moment I do not think that exchange is overly burdensome. * Properly stringify the cookie Cookie values need to be encoded, and they come off the req.cookies already decoded.
40 lines
1.6 KiB
TypeScript
40 lines
1.6 KiB
TypeScript
import * as cookie from "cookie"
|
|
import type { Request } from "express"
|
|
import proxyServer from "http-proxy"
|
|
import { getCookieSessionName, HttpCode } from "../common/http"
|
|
|
|
export const proxy = proxyServer.createProxyServer({})
|
|
|
|
// The error handler catches when the proxy fails to connect (for example when
|
|
// there is nothing running on the target port).
|
|
proxy.on("error", (error, _, res) => {
|
|
// This could be for either a web socket or a regular request. Despite what
|
|
// the types say, writeHead() will not exist on web socket requests (nor will
|
|
// status() from Express). But writing out the code manually does not work
|
|
// for regular requests thus the branching behavior.
|
|
if (typeof res.writeHead !== "undefined") {
|
|
res.writeHead(HttpCode.ServerError)
|
|
res.end(error.message)
|
|
} else {
|
|
res.end(`HTTP/1.1 ${HttpCode.ServerError} ${error.message}\r\n\r\n`)
|
|
}
|
|
})
|
|
|
|
// Strip the code-server cookie if it exists to avoid transmitting the cookie
|
|
// to potentially malicious local ports.
|
|
proxy.on("proxyReq", (preq, req) => {
|
|
const cookieSessionName = getCookieSessionName((req as Request).args["cookie-suffix"])
|
|
preq.setHeader("Cookie", cookie.stringifyCookie({
|
|
...(req as Request).cookies,
|
|
[cookieSessionName]: undefined,
|
|
}))
|
|
})
|
|
|
|
// Intercept the response to rewrite absolute redirects against the base path.
|
|
// Is disabled when the request has no base path which means /absproxy is in use.
|
|
proxy.on("proxyRes", (res, req) => {
|
|
if (res.headers.location && res.headers.location.startsWith("/") && (req as any).base) {
|
|
res.headers.location = (req as any).base + res.headers.location
|
|
}
|
|
})
|