Skip to content

Commit e7c336b

Browse files
committed
Fix listening on a socket
1 parent 64b6f71 commit e7c336b

File tree

6 files changed

+48
-31
lines changed

6 files changed

+48
-31
lines changed

src/node/app.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,10 @@ export const createApp = async (args: DefaultedArgs): Promise<[Express, Express,
6767
/**
6868
* Get the address of a server as a string (protocol *is* included) while
6969
* ensuring there is one (will throw if there isn't).
70+
*
71+
* The address might be a URL or it might be a pipe or socket path.
7072
*/
71-
export const ensureAddress = (server: http.Server, protocol: string): URL => {
73+
export const ensureAddress = (server: http.Server, protocol: string): URL | string => {
7274
const addr = server.address()
7375

7476
if (!addr) {
@@ -79,7 +81,8 @@ export const ensureAddress = (server: http.Server, protocol: string): URL => {
7981
return new URL(`${protocol}://${addr.address}:${addr.port}`)
8082
}
8183

82-
return new URL(addr)
84+
// If this is a string then it is a pipe or Unix socket.
85+
return addr
8386
}
8487

8588
/**

src/node/coder_cloud.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ function runAgent(...args: string[]): Promise<void> {
3333
})
3434
}
3535

36-
export function coderCloudBind(csAddr: string, serverName = ""): Promise<void> {
37-
// addr needs to be in host:port format.
38-
// So we trim the protocol.
39-
csAddr = csAddr.replace(/^https?:\/\//, "")
40-
return runAgent("bind", `--code-server-addr=${csAddr}`, serverName)
36+
export function coderCloudBind(address: URL | string, serverName = ""): Promise<void> {
37+
if (typeof address === "string") {
38+
throw new Error("Cannot link socket paths")
39+
}
40+
41+
// Address needs to be in hostname:port format without the protocol.
42+
return runAgent("bind", `--code-server-addr=${address.host}`, serverName)
4143
}

src/node/link.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import { logger } from "@coder/logger"
22
import { ChildProcessWithoutNullStreams, spawn } from "child_process"
33
import path from "path"
44

5-
export function startLink(port: number): ChildProcessWithoutNullStreams {
6-
logger.debug(`running link targetting ${port}`)
5+
export function startLink(address: URL | string): ChildProcessWithoutNullStreams {
6+
if (typeof address === "string") {
7+
throw new Error("Cannot link socket paths")
8+
}
9+
10+
const port = parseInt(address.port, 10)
11+
logger.debug(`running link targeting ${port}`)
712

813
return spawn(path.resolve(__dirname, "../../lib/linkup"), ["--devurl", `code:${port}:code-server`], {
914
shell: false,

src/node/main.ts

+10-17
Original file line numberDiff line numberDiff line change
@@ -152,26 +152,24 @@ export const runCodeServer = async (
152152
}
153153

154154
if (args.link) {
155-
await coderCloudBind(serverAddress.host, args.link.value)
155+
await coderCloudBind(serverAddress, args.link.value)
156156
logger.info(" - Connected to cloud agent")
157157
}
158158

159159
let linkAgent: undefined | ChildProcessWithoutNullStreams
160160

161161
try {
162-
linkAgent = startLink(parseInt(serverAddress.port, 10))
162+
const linkAgent = startLink(serverAddress)
163+
linkAgent.on("error", (error) => {
164+
logger.debug("[Link daemon]", field("error", error))
165+
})
166+
linkAgent.on("close", (code) => {
167+
logger.debug("[Link daemon]", field("code", `Closed with code ${code}`))
168+
})
163169
} catch (error) {
164170
logger.debug("Failed to start link daemon!", error as any)
165171
}
166172

167-
linkAgent?.on("error", (error) => {
168-
logger.debug("[Link daemon]", field("error", error))
169-
})
170-
171-
linkAgent?.on("close", (code) => {
172-
logger.debug("[Link daemon]", field("code", `Closed with code ${code}`))
173-
})
174-
175173
if (args.enable && args.enable.length > 0) {
176174
logger.info("Enabling the following experimental features:")
177175
args.enable.forEach((feature) => {
@@ -187,14 +185,9 @@ export const runCodeServer = async (
187185
)
188186
}
189187

190-
if (!args.socket && args.open) {
191-
// The web socket doesn't seem to work if browsing with 0.0.0.0.
192-
if (serverAddress.hostname === "0.0.0.0") {
193-
serverAddress.hostname = "localhost"
194-
}
195-
188+
if (args.open) {
196189
try {
197-
await open(serverAddress.toString())
190+
await open(serverAddress)
198191
logger.info(`Opened ${serverAddress}`)
199192
} catch (error) {
200193
logger.error("Failed to open", field("address", serverAddress.toString()), field("error", error))

src/node/util.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -393,19 +393,27 @@ export const isWsl = async (): Promise<boolean> => {
393393
}
394394

395395
/**
396-
* Try opening a URL using whatever the system has set for opening URLs.
396+
* Try opening an address using whatever the system has set for opening URLs.
397397
*/
398-
export const open = async (url: string): Promise<void> => {
398+
export const open = async (address: URL | string): Promise<void> => {
399+
if (typeof address === "string") {
400+
throw new Error("Cannot open socket paths")
401+
}
402+
// Web sockets do not seem to work if browsing with 0.0.0.0.
403+
const url = new URL(address)
404+
if (url.hostname === "0.0.0.0") {
405+
url.hostname = "localhost"
406+
}
399407
const args = [] as string[]
400408
const options = {} as cp.SpawnOptions
401409
const platform = (await isWsl()) ? "wsl" : process.platform
402410
let command = platform === "darwin" ? "open" : "xdg-open"
403411
if (platform === "win32" || platform === "wsl") {
404412
command = platform === "wsl" ? "cmd.exe" : "cmd"
405413
args.push("/c", "start", '""', "/b")
406-
url = url.replace(/&/g, "^&")
414+
url.search = url.search.replace(/&/g, "^&")
407415
}
408-
const proc = cp.spawn(command, [...args, url], options)
416+
const proc = cp.spawn(command, [...args, url.toString()], options)
409417
await new Promise<void>((resolve, reject) => {
410418
proc.on("error", reject)
411419
proc.on("close", (code) => {

test/utils/httpserver.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -101,16 +101,22 @@ export class HttpServer {
101101
*/
102102
public fetch(requestPath: string, opts?: RequestInit): Promise<Response> {
103103
const address = ensureAddress(this.hs, "http")
104+
if (typeof address === "string") {
105+
throw new Error("Cannot fetch socket path")
106+
}
104107
address.pathname = requestPath
105108

106109
return nodeFetch(address.toString(), opts)
107110
}
108111

109112
/**
110-
* Open a websocket against the requset path.
113+
* Open a websocket against the request path.
111114
*/
112115
public ws(requestPath: string): Websocket {
113116
const address = ensureAddress(this.hs, "ws")
117+
if (typeof address === "string") {
118+
throw new Error("Cannot open websocket to socket path")
119+
}
114120
address.pathname = requestPath
115121

116122
return new Websocket(address.toString())

0 commit comments

Comments
 (0)