mirror of https://github.com/coder/code-server.git
Fix HTTPS redirects and TLS sockets
It still won't work behind a base path, but if you're using a reverse proxy you can just redirect to HTTPS yourself. And should probably handle TLS termination there too. For sockets I just needed to add back the proxy call.
This commit is contained in:
parent
e5b68a8f4c
commit
c567a06ff5
|
@ -1,4 +1,4 @@
|
||||||
import { logger } from "@coder/logger"
|
import { field, logger } from "@coder/logger"
|
||||||
import * as fs from "fs-extra"
|
import * as fs from "fs-extra"
|
||||||
import * as http from "http"
|
import * as http from "http"
|
||||||
import * as httpolyglot from "httpolyglot"
|
import * as httpolyglot from "httpolyglot"
|
||||||
|
@ -13,6 +13,7 @@ import * as tls from "tls"
|
||||||
import * as url from "url"
|
import * as url from "url"
|
||||||
import { HttpCode, HttpError } from "../common/http"
|
import { HttpCode, HttpError } from "../common/http"
|
||||||
import { normalize, plural, split } from "../common/util"
|
import { normalize, plural, split } from "../common/util"
|
||||||
|
import { SocketProxyProvider } from "./socket"
|
||||||
import { getMediaMime, xdgLocalDir } from "./util"
|
import { getMediaMime, xdgLocalDir } from "./util"
|
||||||
|
|
||||||
export type Cookies = { [key: string]: string[] | undefined }
|
export type Cookies = { [key: string]: string[] | undefined }
|
||||||
|
@ -370,6 +371,7 @@ export class HttpServer {
|
||||||
public readonly protocol: "http" | "https"
|
public readonly protocol: "http" | "https"
|
||||||
private readonly providers = new Map<string, HttpProvider>()
|
private readonly providers = new Map<string, HttpProvider>()
|
||||||
private readonly heart: Heart
|
private readonly heart: Heart
|
||||||
|
private readonly socketProvider = new SocketProxyProvider()
|
||||||
|
|
||||||
public constructor(private readonly options: HttpServerOptions) {
|
public constructor(private readonly options: HttpServerOptions) {
|
||||||
this.heart = new Heart(path.join(xdgLocalDir, "heartbeat"), async () => {
|
this.heart = new Heart(path.join(xdgLocalDir, "heartbeat"), async () => {
|
||||||
|
@ -392,6 +394,7 @@ export class HttpServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
|
this.socketProvider.stop()
|
||||||
this.providers.forEach((p) => p.dispose())
|
this.providers.forEach((p) => p.dispose())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,6 +513,7 @@ export class HttpServer {
|
||||||
if (error.code === "ENOENT" || error.code === "EISDIR") {
|
if (error.code === "ENOENT" || error.code === "EISDIR") {
|
||||||
e = new HttpError("Not found", HttpCode.NotFound)
|
e = new HttpError("Not found", HttpCode.NotFound)
|
||||||
}
|
}
|
||||||
|
logger.debug("Request error", field("url", request.url))
|
||||||
logger.debug(error.stack)
|
logger.debug(error.stack)
|
||||||
const code = typeof e.code === "number" ? e.code : HttpCode.ServerError
|
const code = typeof e.code === "number" ? e.code : HttpCode.ServerError
|
||||||
const content = (await route.provider.getErrorRoot(route, code, code, e.message)).content
|
const content = (await route.provider.getErrorRoot(route, code, code, e.message)).content
|
||||||
|
@ -547,11 +551,13 @@ export class HttpServer {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
const secure = (request.connection as tls.TLSSocket).encrypted
|
||||||
(this.options.cert ? `${this.protocol}://${request.headers.host}` : "") +
|
const redirect =
|
||||||
|
(this.options.cert && !secure ? `${this.protocol}://${request.headers.host}/` : "") +
|
||||||
normalize(`${route.provider.base(route)}/${payload.redirect}`, true) +
|
normalize(`${route.provider.base(route)}/${payload.redirect}`, true) +
|
||||||
(Object.keys(query).length > 0 ? `?${querystring.stringify(query)}` : "")
|
(Object.keys(query).length > 0 ? `?${querystring.stringify(query)}` : "")
|
||||||
)
|
logger.debug("Redirecting", field("secure", !!secure), field("from", request.url), field("to", redirect))
|
||||||
|
return redirect
|
||||||
}
|
}
|
||||||
|
|
||||||
private onUpgrade = async (request: http.IncomingMessage, socket: net.Socket, head: Buffer): Promise<void> => {
|
private onUpgrade = async (request: http.IncomingMessage, socket: net.Socket, head: Buffer): Promise<void> => {
|
||||||
|
@ -572,7 +578,9 @@ export class HttpServer {
|
||||||
throw new HttpError("Not found", HttpCode.NotFound)
|
throw new HttpError("Not found", HttpCode.NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(await route.provider.handleWebSocket(route, request, socket, head))) {
|
if (
|
||||||
|
!(await route.provider.handleWebSocket(route, request, await this.socketProvider.createProxy(socket), head))
|
||||||
|
) {
|
||||||
throw new HttpError("Not found", HttpCode.NotFound)
|
throw new HttpError("Not found", HttpCode.NotFound)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -609,7 +617,7 @@ export class HttpServer {
|
||||||
|
|
||||||
const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}, pathname: "" }
|
const parsedUrl = request.url ? url.parse(request.url, true) : { query: {}, pathname: "" }
|
||||||
const originalPath = parsedUrl.pathname || "/"
|
const originalPath = parsedUrl.pathname || "/"
|
||||||
const fullPath = normalize(originalPath)
|
const fullPath = normalize(originalPath, true)
|
||||||
const { base, requestPath } = parse(fullPath)
|
const { base, requestPath } = parse(fullPath)
|
||||||
|
|
||||||
// Providers match on the path after their base so we need to account for
|
// Providers match on the path after their base so we need to account for
|
||||||
|
|
Loading…
Reference in New Issue