mirror of https://github.com/coder/code-server.git
Add flag to enable permessage-deflate
This commit is contained in:
parent
92bf2c9760
commit
083400b50a
|
@ -6,6 +6,11 @@ import * as path from "path"
|
||||||
import { Args as VsArgs } from "../../typings/ipc"
|
import { Args as VsArgs } from "../../typings/ipc"
|
||||||
import { canConnect, generateCertificate, generatePassword, humanPath, paths } from "./util"
|
import { canConnect, generateCertificate, generatePassword, humanPath, paths } from "./util"
|
||||||
|
|
||||||
|
export enum Feature {
|
||||||
|
/** Web socket compression. */
|
||||||
|
PermessageDeflate = "permessage-deflate",
|
||||||
|
}
|
||||||
|
|
||||||
export enum AuthType {
|
export enum AuthType {
|
||||||
Password = "password",
|
Password = "password",
|
||||||
None = "none",
|
None = "none",
|
||||||
|
@ -35,6 +40,7 @@ export interface Args extends VsArgs {
|
||||||
"cert-key"?: string
|
"cert-key"?: string
|
||||||
"disable-telemetry"?: boolean
|
"disable-telemetry"?: boolean
|
||||||
"disable-update-check"?: boolean
|
"disable-update-check"?: boolean
|
||||||
|
enable?: string[]
|
||||||
help?: boolean
|
help?: boolean
|
||||||
host?: string
|
host?: string
|
||||||
json?: boolean
|
json?: boolean
|
||||||
|
@ -128,6 +134,9 @@ const options: Options<Required<Args>> = {
|
||||||
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
|
"Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and \n" +
|
||||||
"then notifies you once every week that a new release is available.",
|
"then notifies you once every week that a new release is available.",
|
||||||
},
|
},
|
||||||
|
// --enable can be used to enable experimental features. These features
|
||||||
|
// provide no guarantees.
|
||||||
|
enable: { type: "string[]" },
|
||||||
help: { type: "boolean", short: "h", description: "Show this output." },
|
help: { type: "boolean", short: "h", description: "Show this output." },
|
||||||
json: { type: "boolean" },
|
json: { type: "boolean" },
|
||||||
open: { type: "boolean", description: "Open in browser on startup. Does not work remotely." },
|
open: { type: "boolean", description: "Open in browser on startup. Does not work remotely." },
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { createApp, ensureAddress } from "./app"
|
||||||
import {
|
import {
|
||||||
AuthType,
|
AuthType,
|
||||||
DefaultedArgs,
|
DefaultedArgs,
|
||||||
|
Feature,
|
||||||
optionDescriptions,
|
optionDescriptions,
|
||||||
parse,
|
parse,
|
||||||
readConfigFile,
|
readConfigFile,
|
||||||
|
@ -146,6 +147,21 @@ const main = async (args: DefaultedArgs): Promise<void> => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.enable && args.enable.length > 0) {
|
||||||
|
logger.info("Enabling the following experimental features:")
|
||||||
|
args.enable.forEach((feature) => {
|
||||||
|
if (Object.values(Feature).includes(feature as Feature)) {
|
||||||
|
logger.info(` - "${feature}"`)
|
||||||
|
} else {
|
||||||
|
logger.error(` X "${feature}" (unknown feature)`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// TODO: Could be nice to add wrapping to the logger?
|
||||||
|
logger.info(
|
||||||
|
" The code-server project does not provide stability guarantees or commit to fixing bugs relating to these experimental features. When filing bug reports, please ensure that you can reproduce the bug with all experimental features turned off.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (!args.socket && args.open) {
|
if (!args.socket && args.open) {
|
||||||
// The web socket doesn't seem to work if browsing with 0.0.0.0.
|
// The web socket doesn't seem to work if browsing with 0.0.0.0.
|
||||||
const openAddress = serverAddress.replace("://0.0.0.0", "://localhost")
|
const openAddress = serverAddress.replace("://0.0.0.0", "://localhost")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import * as ipc from "../../../typings/ipc"
|
||||||
import { Emitter } from "../../common/emitter"
|
import { Emitter } from "../../common/emitter"
|
||||||
import { HttpCode, HttpError } from "../../common/http"
|
import { HttpCode, HttpError } from "../../common/http"
|
||||||
import { getFirstString } from "../../common/util"
|
import { getFirstString } from "../../common/util"
|
||||||
|
import { Feature } from "../cli"
|
||||||
import { isDevMode, rootPath, version } from "../constants"
|
import { isDevMode, rootPath, version } from "../constants"
|
||||||
import { authenticated, ensureAuthenticated, redirect, replaceTemplates } from "../http"
|
import { authenticated, ensureAuthenticated, redirect, replaceTemplates } from "../http"
|
||||||
import { getMediaMime, pathToFsPath } from "../util"
|
import { getMediaMime, pathToFsPath } from "../util"
|
||||||
|
@ -209,14 +210,21 @@ wsRouter.ws("/", ensureAuthenticated, async (req) => {
|
||||||
`Sec-WebSocket-Accept: ${reply}`,
|
`Sec-WebSocket-Accept: ${reply}`,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
// See if the browser reports it supports web socket compression.
|
||||||
// TODO: Parse this header properly.
|
// TODO: Parse this header properly.
|
||||||
const extensions = req.headers["sec-websocket-extensions"]
|
const extensions = req.headers["sec-websocket-extensions"]
|
||||||
const permessageDeflate = extensions ? extensions.includes("permessage-deflate") : false
|
const isCompressionSupported = extensions ? extensions.includes("permessage-deflate") : false
|
||||||
if (permessageDeflate) {
|
|
||||||
|
// TODO: For now we only use compression if the user enables it.
|
||||||
|
const isCompressionEnabled = !!req.args.enable?.includes(Feature.PermessageDeflate)
|
||||||
|
|
||||||
|
const useCompression = isCompressionEnabled && isCompressionSupported
|
||||||
|
if (useCompression) {
|
||||||
|
// This response header tells the browser the server supports compression.
|
||||||
responseHeaders.push("Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15")
|
responseHeaders.push("Sec-WebSocket-Extensions: permessage-deflate; server_max_window_bits=15")
|
||||||
}
|
}
|
||||||
|
|
||||||
req.ws.write(responseHeaders.join("\r\n") + "\r\n\r\n")
|
req.ws.write(responseHeaders.join("\r\n") + "\r\n\r\n")
|
||||||
|
|
||||||
await vscode.sendWebsocket(req.ws, req.query, permessageDeflate)
|
await vscode.sendWebsocket(req.ws, req.query, useCompression)
|
||||||
})
|
})
|
||||||
|
|
|
@ -39,6 +39,10 @@ describe("parser", () => {
|
||||||
it("should parse all available options", () => {
|
it("should parse all available options", () => {
|
||||||
expect(
|
expect(
|
||||||
parse([
|
parse([
|
||||||
|
"--enable",
|
||||||
|
"feature1",
|
||||||
|
"--enable",
|
||||||
|
"feature2",
|
||||||
"--bind-addr=192.169.0.1:8080",
|
"--bind-addr=192.169.0.1:8080",
|
||||||
"--auth",
|
"--auth",
|
||||||
"none",
|
"none",
|
||||||
|
@ -82,6 +86,7 @@ describe("parser", () => {
|
||||||
cert: {
|
cert: {
|
||||||
value: path.resolve("baz"),
|
value: path.resolve("baz"),
|
||||||
},
|
},
|
||||||
|
enable: ["feature1", "feature2"],
|
||||||
"extensions-dir": path.resolve("foo"),
|
"extensions-dir": path.resolve("foo"),
|
||||||
"extra-builtin-extensions-dir": [path.resolve("bazzle")],
|
"extra-builtin-extensions-dir": [path.resolve("bazzle")],
|
||||||
"extra-extensions-dir": [path.resolve("nozzle")],
|
"extra-extensions-dir": [path.resolve("nozzle")],
|
||||||
|
|
Loading…
Reference in New Issue