Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ddcf22c

Browse files
Switch to Express
It doesn't do anything yet.
1 parent 8e93e28 commit ddcf22c

File tree

3 files changed

+84
-58
lines changed

3 files changed

+84
-58
lines changed

‎src/node/app.ts‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { logger } from "@coder/logger"
2+
import express, { Express } from "express"
3+
import { promises as fs } from "fs"
4+
import http from "http"
5+
import * as httpolyglot from "httpolyglot"
6+
import { DefaultedArgs } from "./cli"
7+
8+
/**
9+
* Create an Express app and an HTTP/S server to serve it.
10+
*/
11+
export const createApp = async (args: DefaultedArgs): Promise<[Express, http.Server]> => {
12+
const app = express()
13+
14+
const server = args.cert
15+
? httpolyglot.createServer(
16+
{
17+
cert: args.cert && (await fs.readFile(args.cert.value)),
18+
key: args["cert-key"] && (await fs.readFile(args["cert-key"])),
19+
},
20+
app,
21+
)
22+
: http.createServer(app)
23+
24+
await new Promise<http.Server>(async (resolve, reject) => {
25+
server.on("error", reject)
26+
if (args.socket) {
27+
try {
28+
await fs.unlink(args.socket)
29+
} catch (error) {
30+
if (error.code !== "ENOENT") {
31+
logger.error(error.message)
32+
}
33+
}
34+
server.listen(args.socket, resolve)
35+
} else {
36+
// [] is the correct format when using :: but Node errors with them.
37+
server.listen(args.port, args.host.replace(/^\[|\]$/g, ""), resolve)
38+
}
39+
})
40+
41+
return [app, server]
42+
}
43+
44+
/**
45+
* Get the address of a server as a string (protocol not included) while
46+
* ensuring there is one (will throw if there isn't).
47+
*/
48+
export const ensureAddress = (server: http.Server): string => {
49+
const addr = server.address()
50+
if (!addr) {
51+
throw new Error("server has no address")
52+
}
53+
if (typeof addr !== "string") {
54+
return `${addr.address}:${addr.port}`
55+
}
56+
return addr
57+
}

‎src/node/entry.ts‎

Lines changed: 17 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,9 @@ import http from "http"
55
import * as path from "path"
66
import { CliMessage, OpenCommandPipeArgs } from "../../lib/vscode/src/vs/server/ipc"
77
import { plural } from "../common/util"
8-
import { HealthHttpProvider } from "./routes/health"
9-
import { LoginHttpProvider } from "./routes/login"
10-
import { ProxyHttpProvider } from "./routes/proxy"
11-
import { StaticHttpProvider } from "./routes/static"
12-
import { UpdateHttpProvider } from "./routes/update"
13-
import { VscodeHttpProvider } from "./routes/vscode"
8+
import { createApp, ensureAddress } from "./app"
149
import {
10+
AuthType,
1511
DefaultedArgs,
1612
optionDescriptions,
1713
parse,
@@ -21,9 +17,8 @@ import {
2117
shouldRunVsCodeCli,
2218
} from "./cli"
2319
import { coderCloudBind } from "./coder-cloud"
24-
import { AuthType, HttpServer, HttpServerOptions } from "./http"
2520
import { loadPlugins } from "./plugin"
26-
import { hash,humanPath, open } from "./util"
21+
import { humanPath, open } from "./util"
2722
import { ipcMain, WrapperProcess } from "./wrapper"
2823

2924
let pkg: { version?: string; commit?: string } = {}
@@ -117,65 +112,39 @@ export const openInExistingInstance = async (args: DefaultedArgs, socketPath: st
117112
}
118113

119114
const main = async (args: DefaultedArgs): Promise<void> => {
115+
logger.info(`code-server ${version} ${commit}`)
116+
120117
logger.info(`Using user-data-dir ${humanPath(args["user-data-dir"])}`)
121118
logger.trace(`Using extensions-dir ${humanPath(args["extensions-dir"])}`)
122119

123120
if (args.auth === AuthType.Password && !args.password) {
124121
throw new Error("Please pass in a password via the config file or $PASSWORD")
125122
}
126-
127-
// Spawn the main HTTP server.
128-
const options: HttpServerOptions = {
129-
auth: args.auth,
130-
commit,
131-
host: args.host,
132-
// The hash does not add any actual security but we do it for obfuscation purposes.
133-
password: args.password ? hash(args.password) : undefined,
134-
port: args.port,
135-
proxyDomains: args["proxy-domain"],
136-
socket: args.socket,
137-
cert: args.cert && args.cert.value,
138-
certKey: args["cert-key"],
139-
}
140-
141-
if (options.cert && !options.certKey) {
142-
throw new Error("--cert-key is missing")
143-
}
144-
145-
const httpServer = new HttpServer(options)
146-
httpServer.registerHttpProvider(["/", "/vscode"], VscodeHttpProvider, args)
147-
httpServer.registerHttpProvider("/update", UpdateHttpProvider, false)
148-
httpServer.registerHttpProvider("/proxy", ProxyHttpProvider)
149-
httpServer.registerHttpProvider("/login", LoginHttpProvider, args.config!, args.usingEnvPassword)
150-
httpServer.registerHttpProvider("/static", StaticHttpProvider)
151-
httpServer.registerHttpProvider("/healthz", HealthHttpProvider, httpServer.heart)
152-
153-
await loadPlugins(httpServer, args)
154-
155123
ipcMain.onDispose(() => {
156-
httpServer.dispose().then((errors) => {
157-
errors.forEach((error) => logger.error(error.message))
158-
})
124+
// TODO: register disposables
159125
})
160126

161-
logger.info(`code-server ${version} ${commit}`)
162-
logger.info(`Using config file ${humanPath(args.config)}`)
127+
const [app, server] = await createApp(args)
128+
const serverAddress = ensureAddress(server)
129+
130+
// TODO: register routes
131+
await loadPlugins(app, args)
163132

164-
constserverAddress=awaithttpServer.listen()
133+
logger.info(`Using config file ${humanPath(args.config)}`)
165134
logger.info(`HTTP server listening on ${serverAddress} ${args.link ? "(randomized by --link)" : ""}`)
166135

167136
if (args.auth === AuthType.Password) {
137+
logger.info(" - Authentication is enabled")
168138
if (args.usingEnvPassword) {
169139
logger.info(" - Using password from $PASSWORD")
170140
} else {
171141
logger.info(` - Using password from ${humanPath(args.config)}`)
172142
}
173-
logger.info(" - To disable use `--auth none`")
174143
} else {
175-
logger.info(` - No authentication ${args.link ? "(disabled by --link)" : ""}`)
144+
logger.info(` - Authentication is disabled ${args.link ? "(disabled by --link)" : ""}`)
176145
}
177146

178-
if (httpServer.protocol==="https") {
147+
if (args.cert) {
179148
logger.info(
180149
args.cert && args.cert.value
181150
? ` - Using provided certificate and key for HTTPS`
@@ -192,15 +161,15 @@ const main = async (args: DefaultedArgs): Promise<void> => {
192161

193162
if (args.link) {
194163
try {
195-
await coderCloudBind(serverAddress!, args.link.value)
164+
await coderCloudBind(serverAddress, args.link.value)
196165
logger.info(" - Connected to cloud agent")
197166
} catch (err) {
198167
logger.error(err.message)
199168
ipcMain.exit(1)
200169
}
201170
}
202171

203-
if (serverAddress && !options.socket && args.open) {
172+
if (typeofserverAddress ==="string"&& !args.socket && args.open) {
204173
// The web socket doesn't seem to work if browsing with 0.0.0.0.
205174
const openAddress = serverAddress.replace(/:\/\/0.0.0.0/, "://localhost")
206175
await open(openAddress).catch((error: Error) => {

‎src/node/plugin.ts‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { field, logger } from "@coder/logger"
2+
import { Express } from "express"
23
import * as fs from "fs"
34
import * as path from "path"
45
import * as util from "util"
56
import { Args } from "./cli"
6-
import { HttpServer } from "./http"
77
import { paths } from "./util"
88

99
/* eslint-disable @typescript-eslint/no-var-requires */
1010

11-
export type Activate = (httpServer: HttpServer, args: Args) => void
11+
export type Activate = (app: Express, args: Args) => void
1212

1313
/**
1414
* Plugins must implement this interface.
@@ -30,10 +30,10 @@ require("module")._load = function (request: string, parent: object, isMain: boo
3030
/**
3131
* Load a plugin and run its activation function.
3232
*/
33-
const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args): Promise<void> => {
33+
const loadPlugin = async (pluginPath: string, app: Express, args: Args): Promise<void> => {
3434
try {
3535
const plugin: Plugin = require(pluginPath)
36-
plugin.activate(httpServer, args)
36+
plugin.activate(app, args)
3737

3838
const packageJson = require(path.join(pluginPath, "package.json"))
3939
logger.debug(
@@ -50,12 +50,12 @@ const loadPlugin = async (pluginPath: string, httpServer: HttpServer, args: Args
5050
/**
5151
* Load all plugins in the specified directory.
5252
*/
53-
const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Args): Promise<void> => {
53+
const _loadPlugins = async (pluginDir: string, app: Express, args: Args): Promise<void> => {
5454
try {
5555
const files = await util.promisify(fs.readdir)(pluginDir, {
5656
withFileTypes: true,
5757
})
58-
await Promise.all(files.map((file) => loadPlugin(path.join(pluginDir, file.name), httpServer, args)))
58+
await Promise.all(files.map((file) => loadPlugin(path.join(pluginDir, file.name), app, args)))
5959
} catch (error) {
6060
if (error.code !== "ENOENT") {
6161
logger.warn(error.message)
@@ -68,17 +68,17 @@ const _loadPlugins = async (pluginDir: string, httpServer: HttpServer, args: Arg
6868
* `CS_PLUGIN_PATH` (colon-separated), and individual plugins specified by
6969
* `CS_PLUGIN` (also colon-separated).
7070
*/
71-
export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise<void> => {
71+
export const loadPlugins = async (app: Express, args: Args): Promise<void> => {
7272
const pluginPath = process.env.CS_PLUGIN_PATH || `${path.join(paths.data, "plugins")}:/usr/share/code-server/plugins`
7373
const plugin = process.env.CS_PLUGIN || ""
7474
await Promise.all([
7575
// Built-in plugins.
76-
_loadPlugins(path.resolve(__dirname, "../../plugins"), httpServer, args),
76+
_loadPlugins(path.resolve(__dirname, "../../plugins"), app, args),
7777
// User-added plugins.
7878
...pluginPath
7979
.split(":")
8080
.filter((p) => !!p)
81-
.map((dir) => _loadPlugins(path.resolve(dir), httpServer, args)),
81+
.map((dir) => _loadPlugins(path.resolve(dir), app, args)),
8282
// Individual plugins so you don't have to symlink or move them into a
8383
// directory specifically for plugins. This lets you load plugins that are
8484
// on the same level as other directories that are not plugins (if you tried
@@ -87,6 +87,6 @@ export const loadPlugins = async (httpServer: HttpServer, args: Args): Promise<v
8787
...plugin
8888
.split(":")
8989
.filter((p) => !!p)
90-
.map((dir) => loadPlugin(path.resolve(dir), httpServer, args)),
90+
.map((dir) => loadPlugin(path.resolve(dir), app, args)),
9191
])
9292
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /