Spawn vscode on demand (#4499)

* Refactor vscode router to load async.

* Bump vscode.

* fix volumes (#4497)

* Fix : recreate the termux guide to adapt the recent changes (#4472)

* Fix : recreate the termux guide to adapt the recent changes

Termux nodejs-lts changed from v14 to v16 and there are many issues people are facing such as with argon2. Hence I recommend changing it to this install process which is comparably better and has one less issue :^)

I've also added some extra things such as installing GO and Python, idk about the TOC tree but this is pretty much it.

* yarn-fmt and minor typos

https://github.com/cdr/code-server/pull/4472#issuecomment-964752180

* Fix : replace unnecessary steps to be linked to a guide

* Change from private gist to a section in Extra

* Remove reference to non-existent step

* ready to merge!

Co-authored-by: Joe Previte <jjprevite@gmail.com>

Co-authored-by: Jinu <jlandowner8@gmail.com>
Co-authored-by: Han Seung Min - 한승민 <hanseungmin.ar@gmail.com>
Co-authored-by: Joe Previte <jjprevite@gmail.com>
This commit is contained in:
Teffen 2021-11-14 20:03:20 -05:00 committed by GitHub
parent 6606040835
commit e705948ef3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 89 additions and 57 deletions

View File

@ -10,7 +10,7 @@ import { HttpCode, HttpError } from "../../common/http"
import { plural } from "../../common/util" import { plural } from "../../common/util"
import { App } from "../app" import { App } from "../app"
import { AuthType, DefaultedArgs } from "../cli" import { AuthType, DefaultedArgs } from "../cli"
import { commit, isDevMode, rootPath } from "../constants" import { commit, rootPath } from "../constants"
import { Heart } from "../heart" import { Heart } from "../heart"
import { ensureAuthenticated, redirect } from "../http" import { ensureAuthenticated, redirect } from "../http"
import { PluginAPI } from "../plugin" import { PluginAPI } from "../plugin"
@ -23,7 +23,7 @@ import * as login from "./login"
import * as logout from "./logout" import * as logout from "./logout"
import * as pathProxy from "./pathProxy" import * as pathProxy from "./pathProxy"
import * as update from "./update" import * as update from "./update"
import { createVSServerRouter, VSServerResult } from "./vscode" import { CodeServerRouteWrapper } from "./vscode"
/** /**
* Register all routes and middleware. * Register all routes and middleware.
@ -138,20 +138,12 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
app.router.use("/update", update.router) app.router.use("/update", update.router)
let vscode: VSServerResult const vsServerRouteHandler = new CodeServerRouteWrapper()
try {
vscode = await createVSServerRouter(args) // Note that the root route is replaced in Coder Enterprise by the plugin API.
app.router.use("/", vscode.router) for (const routePrefix of ["/", "/vscode"]) {
app.wsRouter.use("/", vscode.wsRouter.router) app.router.use(routePrefix, vsServerRouteHandler.router)
app.router.use("/vscode", vscode.router) app.wsRouter.use(routePrefix, vsServerRouteHandler.wsRouter)
app.wsRouter.use("/vscode", vscode.wsRouter.router)
} catch (error: any) {
if (isDevMode) {
logger.warn(error)
logger.warn("VS Server router may still be compiling.")
} else {
throw error
}
} }
app.router.use(() => { app.router.use(() => {
@ -164,6 +156,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
return () => { return () => {
heart.dispose() heart.dispose()
pluginApi?.dispose() pluginApi?.dispose()
vscode?.codeServerMain.dispose() vsServerRouteHandler.dispose()
} }
} }

View File

@ -1,65 +1,105 @@
import { logger } from "@coder/logger"
import * as express from "express" import * as express from "express"
import { DefaultedArgs } from "../cli" import { WebsocketRequest } from "../../../typings/pluginapi"
import { logError } from "../../common/util"
import { isDevMode } from "../constants"
import { ensureAuthenticated, authenticated, redirect } from "../http" import { ensureAuthenticated, authenticated, redirect } from "../http"
import { loadAMDModule } from "../util" import { loadAMDModule } from "../util"
import { Router as WsRouter, WebsocketRouter } from "../wsRouter" import { Router as WsRouter } from "../wsRouter"
import { errorHandler } from "./errors" import { errorHandler } from "./errors"
export interface VSServerResult { export class CodeServerRouteWrapper {
router: express.Router /** Assigned in `ensureCodeServerLoaded` */
wsRouter: WebsocketRouter private _codeServerMain!: CodeServerLib.IServerAPI
codeServerMain: CodeServerLib.IServerAPI private _wsRouterWrapper = WsRouter()
public router = express.Router()
public get wsRouter() {
return this._wsRouterWrapper.router
} }
export const createVSServerRouter = async (args: DefaultedArgs): Promise<VSServerResult> => { //#region Route Handlers
// See ../../../vendor/modules/code-oss-dev/src/vs/server/main.js.
const createVSServer = await loadAMDModule<CodeServerLib.CreateServer>(
"vs/server/remoteExtensionHostAgent",
"createServer",
)
const codeServerMain = await createVSServer(null, { private $root: express.Handler = async (req, res, next) => {
connectionToken: "0000",
...args,
// For some reason VS Code takes the port as a string.
port: typeof args.port !== "undefined" ? args.port.toString() : undefined,
})
const router = express.Router()
const wsRouter = WsRouter()
router.get("/", async (req, res, next) => {
const isAuthenticated = await authenticated(req) const isAuthenticated = await authenticated(req)
if (!isAuthenticated) { if (!isAuthenticated) {
return redirect(req, res, "login", { return redirect(req, res, "login", {
// req.baseUrl can be blank if already at the root. // req.baseUrl can be blank if already at the root.
to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined, to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined,
}) })
} }
next()
})
router.all("*", ensureAuthenticated, (req, res, next) => { next()
req.on("error", (error: any) => { }
private $proxyRequest: express.Handler = async (req, res, next) => {
// We allow certain errors to propagate so that other routers may handle requests
// outside VS Code
const requestErrorHandler = (error: any) => {
if (error instanceof Error && ["EntryNotFound", "FileNotFound", "HttpError"].includes(error.message)) { if (error instanceof Error && ["EntryNotFound", "FileNotFound", "HttpError"].includes(error.message)) {
next() next()
} }
errorHandler(error, req, res, next) errorHandler(error, req, res, next)
}) }
codeServerMain.handleRequest(req, res) req.once("error", requestErrorHandler)
})
wsRouter.ws("/", ensureAuthenticated, (req) => { this._codeServerMain.handleRequest(req, res)
codeServerMain.handleUpgrade(req, req.socket) }
private $proxyWebsocket = async (req: WebsocketRequest) => {
this._codeServerMain.handleUpgrade(req, req.socket)
req.socket.resume() req.socket.resume()
}) }
return { //#endregion
router,
wsRouter, /**
codeServerMain, * Fetches a code server instance asynchronously to avoid an initial memory overhead.
*/
private ensureCodeServerLoaded: express.Handler = async (req, _res, next) => {
if (this._codeServerMain) {
return next()
}
const { args } = req
/**
* @file ../../../vendor/modules/code-oss-dev/src/vs/server/main.js
*/
const createVSServer = await loadAMDModule<CodeServerLib.CreateServer>(
"vs/server/remoteExtensionHostAgent",
"createServer",
)
try {
this._codeServerMain = await createVSServer(null, {
connectionToken: "0000",
...args,
// For some reason VS Code takes the port as a string.
port: args.port?.toString(),
})
} catch (createServerError) {
logError(logger, "CodeServerRouteWrapper", createServerError)
const loggedError = isDevMode ? new Error("VS Code may still be compiling...") : createServerError
return next(loggedError)
}
return next()
}
constructor() {
this.router.get("/", this.ensureCodeServerLoaded, this.$root)
this.router.all("*", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyRequest)
this._wsRouterWrapper.ws("/", ensureAuthenticated, this.ensureCodeServerLoaded, this.$proxyWebsocket)
}
dispose() {
this._codeServerMain?.dispose()
} }
} }

2
vendor/package.json vendored
View File

@ -7,6 +7,6 @@
"postinstall": "./postinstall.sh" "postinstall": "./postinstall.sh"
}, },
"devDependencies": { "devDependencies": {
"code-oss-dev": "cdr/vscode#d62e8db202f80db7a42233cd56d04e6806109fb1" "code-oss-dev": "cdr/vscode#8db6c9bb0bc065bdb905dc076f4d4234f126aff7"
} }
} }

4
vendor/yarn.lock vendored
View File

@ -296,9 +296,9 @@ clone-response@^1.0.2:
dependencies: dependencies:
mimic-response "^1.0.0" mimic-response "^1.0.0"
code-oss-dev@cdr/vscode#d62e8db202f80db7a42233cd56d04e6806109fb1: code-oss-dev@cdr/vscode#8db6c9bb0bc065bdb905dc076f4d4234f126aff7:
version "1.61.1" version "1.61.1"
resolved "https://codeload.github.com/cdr/vscode/tar.gz/d62e8db202f80db7a42233cd56d04e6806109fb1" resolved "https://codeload.github.com/cdr/vscode/tar.gz/8db6c9bb0bc065bdb905dc076f4d4234f126aff7"
dependencies: dependencies:
"@microsoft/applicationinsights-web" "^2.6.4" "@microsoft/applicationinsights-web" "^2.6.4"
"@vscode/sqlite3" "4.0.12" "@vscode/sqlite3" "4.0.12"