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 { App } from "../app"
import { AuthType, DefaultedArgs } from "../cli"
import { commit, isDevMode, rootPath } from "../constants"
import { commit, rootPath } from "../constants"
import { Heart } from "../heart"
import { ensureAuthenticated, redirect } from "../http"
import { PluginAPI } from "../plugin"
@ -23,7 +23,7 @@ import * as login from "./login"
import * as logout from "./logout"
import * as pathProxy from "./pathProxy"
import * as update from "./update"
import { createVSServerRouter, VSServerResult } from "./vscode"
import { CodeServerRouteWrapper } from "./vscode"
/**
* 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)
let vscode: VSServerResult
try {
vscode = await createVSServerRouter(args)
app.router.use("/", vscode.router)
app.wsRouter.use("/", vscode.wsRouter.router)
app.router.use("/vscode", vscode.router)
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
}
const vsServerRouteHandler = new CodeServerRouteWrapper()
// Note that the root route is replaced in Coder Enterprise by the plugin API.
for (const routePrefix of ["/", "/vscode"]) {
app.router.use(routePrefix, vsServerRouteHandler.router)
app.wsRouter.use(routePrefix, vsServerRouteHandler.wsRouter)
}
app.router.use(() => {
@ -164,6 +156,6 @@ export const register = async (app: App, args: DefaultedArgs): Promise<Disposabl
return () => {
heart.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 { DefaultedArgs } from "../cli"
import { WebsocketRequest } from "../../../typings/pluginapi"
import { logError } from "../../common/util"
import { isDevMode } from "../constants"
import { ensureAuthenticated, authenticated, redirect } from "../http"
import { loadAMDModule } from "../util"
import { Router as WsRouter, WebsocketRouter } from "../wsRouter"
import { Router as WsRouter } from "../wsRouter"
import { errorHandler } from "./errors"
export interface VSServerResult {
router: express.Router
wsRouter: WebsocketRouter
codeServerMain: CodeServerLib.IServerAPI
export class CodeServerRouteWrapper {
/** Assigned in `ensureCodeServerLoaded` */
private _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> => {
// See ../../../vendor/modules/code-oss-dev/src/vs/server/main.js.
const createVSServer = await loadAMDModule<CodeServerLib.CreateServer>(
"vs/server/remoteExtensionHostAgent",
"createServer",
)
//#region Route Handlers
const codeServerMain = await createVSServer(null, {
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) => {
private $root: express.Handler = async (req, res, next) => {
const isAuthenticated = await authenticated(req)
if (!isAuthenticated) {
return redirect(req, res, "login", {
// req.baseUrl can be blank if already at the root.
to: req.baseUrl && req.baseUrl !== "/" ? req.baseUrl : undefined,
})
}
next()
})
router.all("*", ensureAuthenticated, (req, res, next) => {
req.on("error", (error: any) => {
next()
}
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)) {
next()
}
errorHandler(error, req, res, next)
})
}
codeServerMain.handleRequest(req, res)
})
req.once("error", requestErrorHandler)
wsRouter.ws("/", ensureAuthenticated, (req) => {
codeServerMain.handleUpgrade(req, req.socket)
this._codeServerMain.handleRequest(req, res)
}
private $proxyWebsocket = async (req: WebsocketRequest) => {
this._codeServerMain.handleUpgrade(req, req.socket)
req.socket.resume()
})
}
return {
router,
wsRouter,
codeServerMain,
//#endregion
/**
* 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"
},
"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:
mimic-response "^1.0.0"
code-oss-dev@cdr/vscode#d62e8db202f80db7a42233cd56d04e6806109fb1:
code-oss-dev@cdr/vscode#8db6c9bb0bc065bdb905dc076f4d4234f126aff7:
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:
"@microsoft/applicationinsights-web" "^2.6.4"
"@vscode/sqlite3" "4.0.12"