mirror of https://github.com/coder/code-server.git
Improve HTTP provider registration
This commit is contained in:
parent
4a54e914fc
commit
dbc5c065f8
|
@ -18,7 +18,7 @@ interface LoginPayload extends PostData {
|
||||||
export class ApiHttpProvider extends HttpProvider {
|
export class ApiHttpProvider extends HttpProvider {
|
||||||
private readonly ws = new ws.Server({ noServer: true })
|
private readonly ws = new ws.Server({ noServer: true })
|
||||||
|
|
||||||
public constructor(private readonly server: HttpServer, options: HttpProviderOptions) {
|
public constructor(options: HttpProviderOptions, private readonly server: HttpServer) {
|
||||||
super(options)
|
super(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,9 @@ export interface Args {
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = async (args: Args = {}): Promise<void> => {
|
const main = async (args: Args = {}): Promise<void> => {
|
||||||
|
const auth = args.auth || AuthType.Password
|
||||||
|
const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword()))
|
||||||
|
|
||||||
// Spawn the main HTTP server.
|
// Spawn the main HTTP server.
|
||||||
const options = {
|
const options = {
|
||||||
basePath: args["base-path"],
|
basePath: args["base-path"],
|
||||||
|
@ -28,6 +31,8 @@ const main = async (args: Args = {}): Promise<void> => {
|
||||||
host: args.host || (args.auth === AuthType.Password && typeof args.cert !== "undefined" ? "0.0.0.0" : "localhost"),
|
host: args.host || (args.auth === AuthType.Password && typeof args.cert !== "undefined" ? "0.0.0.0" : "localhost"),
|
||||||
port: typeof args.port !== "undefined" ? parseInt(args.port, 10) : 8080,
|
port: typeof args.port !== "undefined" ? parseInt(args.port, 10) : 8080,
|
||||||
socket: args.socket,
|
socket: args.socket,
|
||||||
|
auth,
|
||||||
|
password: originalPassword ? hash(originalPassword) : undefined,
|
||||||
}
|
}
|
||||||
if (!options.cert && typeof options.cert !== "undefined") {
|
if (!options.cert && typeof options.cert !== "undefined") {
|
||||||
const { cert, certKey } = await generateCertificate()
|
const { cert, certKey } = await generateCertificate()
|
||||||
|
@ -37,17 +42,9 @@ const main = async (args: Args = {}): Promise<void> => {
|
||||||
const httpServer = new HttpServer(options)
|
const httpServer = new HttpServer(options)
|
||||||
|
|
||||||
// Register all the providers.
|
// Register all the providers.
|
||||||
// TODO: Might be cleaner to be able to register with just the class name
|
httpServer.registerHttpProvider("/", MainHttpProvider)
|
||||||
// then let HttpServer instantiate with the common arguments.
|
httpServer.registerHttpProvider("/api", ApiHttpProvider, httpServer)
|
||||||
const auth = args.auth || AuthType.Password
|
httpServer.registerHttpProvider("/vscode-embed", VscodeHttpProvider, [])
|
||||||
const originalPassword = auth === AuthType.Password && (process.env.PASSWORD || (await generatePassword()))
|
|
||||||
const password = originalPassword && hash(originalPassword)
|
|
||||||
httpServer.registerHttpProvider("/", new MainHttpProvider({ base: "/", auth, password }))
|
|
||||||
httpServer.registerHttpProvider("/api", new ApiHttpProvider(httpServer, { base: "/", auth, password }))
|
|
||||||
httpServer.registerHttpProvider(
|
|
||||||
"/vscode-embed",
|
|
||||||
new VscodeHttpProvider([], { base: "/vscode-embed", auth, password })
|
|
||||||
)
|
|
||||||
|
|
||||||
ipcMain().onDispose(() => httpServer.dispose())
|
ipcMain().onDispose(() => httpServer.dispose())
|
||||||
|
|
||||||
|
|
|
@ -88,10 +88,12 @@ export interface HttpStringFileResponse extends HttpResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface HttpServerOptions {
|
export interface HttpServerOptions {
|
||||||
|
readonly auth?: AuthType
|
||||||
readonly basePath?: string
|
readonly basePath?: string
|
||||||
readonly cert?: string
|
readonly cert?: string
|
||||||
readonly certKey?: string
|
readonly certKey?: string
|
||||||
readonly host?: string
|
readonly host?: string
|
||||||
|
readonly password?: string
|
||||||
readonly port?: number
|
readonly port?: number
|
||||||
readonly socket?: string
|
readonly socket?: string
|
||||||
}
|
}
|
||||||
|
@ -108,7 +110,7 @@ interface ProviderRoute {
|
||||||
export interface HttpProviderOptions {
|
export interface HttpProviderOptions {
|
||||||
readonly base: string
|
readonly base: string
|
||||||
readonly auth: AuthType
|
readonly auth: AuthType
|
||||||
readonly password: string | false
|
readonly password?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -320,6 +322,14 @@ export class Heart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HttpProvider0<T> {
|
||||||
|
new (options: HttpProviderOptions): T
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HttpProvider1<A1, T> {
|
||||||
|
new (options: HttpProviderOptions, a1: A1): T
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An HTTP server. Its main role is to route incoming HTTP requests to the
|
* An HTTP server. Its main role is to route incoming HTTP requests to the
|
||||||
* appropriate provider for that endpoint then write out the response. It also
|
* appropriate provider for that endpoint then write out the response. It also
|
||||||
|
@ -372,7 +382,14 @@ export class HttpServer {
|
||||||
/**
|
/**
|
||||||
* Register a provider for a top-level endpoint.
|
* Register a provider for a top-level endpoint.
|
||||||
*/
|
*/
|
||||||
public registerHttpProvider<T extends HttpProvider>(endpoint: string, provider: T): void {
|
public registerHttpProvider<T extends HttpProvider>(endpoint: string, provider: HttpProvider0<T>): void
|
||||||
|
public registerHttpProvider<A1, T extends HttpProvider>(
|
||||||
|
endpoint: string,
|
||||||
|
provider: HttpProvider1<A1, T>,
|
||||||
|
a1: A1
|
||||||
|
): void
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
public registerHttpProvider(endpoint: string, provider: any, a1?: any): void {
|
||||||
endpoint = endpoint.replace(/^\/+|\/+$/g, "")
|
endpoint = endpoint.replace(/^\/+|\/+$/g, "")
|
||||||
if (this.providers.has(`/${endpoint}`)) {
|
if (this.providers.has(`/${endpoint}`)) {
|
||||||
throw new Error(`${endpoint} is already registered`)
|
throw new Error(`${endpoint} is already registered`)
|
||||||
|
@ -380,7 +397,17 @@ export class HttpServer {
|
||||||
if (/\//.test(endpoint)) {
|
if (/\//.test(endpoint)) {
|
||||||
throw new Error(`Only top-level endpoints are supported (got ${endpoint})`)
|
throw new Error(`Only top-level endpoints are supported (got ${endpoint})`)
|
||||||
}
|
}
|
||||||
this.providers.set(`/${endpoint}`, provider)
|
this.providers.set(
|
||||||
|
`/${endpoint}`,
|
||||||
|
new provider(
|
||||||
|
{
|
||||||
|
auth: this.options.auth || AuthType.None,
|
||||||
|
base: endpoint,
|
||||||
|
password: this.options.password,
|
||||||
|
},
|
||||||
|
a1
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,7 +24,7 @@ export class VscodeHttpProvider extends HttpProvider {
|
||||||
private _vscode?: Promise<cp.ChildProcess>
|
private _vscode?: Promise<cp.ChildProcess>
|
||||||
private workbenchOptions?: WorkbenchOptions
|
private workbenchOptions?: WorkbenchOptions
|
||||||
|
|
||||||
public constructor(private readonly args: string[], options: HttpProviderOptions) {
|
public constructor(options: HttpProviderOptions, private readonly args: string[]) {
|
||||||
super(options)
|
super(options)
|
||||||
this.vsRootPath = path.resolve(this.rootPath, "lib/vscode")
|
this.vsRootPath = path.resolve(this.rootPath, "lib/vscode")
|
||||||
this.serverRootPath = path.join(this.vsRootPath, "out/vs/server")
|
this.serverRootPath = path.join(this.vsRootPath, "out/vs/server")
|
||||||
|
|
Loading…
Reference in New Issue