serve: require explicit tcp listener type
This commit is contained in:
parent
25400f48df
commit
d1f44d4cd2
6 changed files with 22 additions and 24 deletions
|
|
@ -72,7 +72,7 @@ export const rpc = {
|
|||
},
|
||||
async server(input: { port: number; hostname: string; mdns?: boolean; cors?: string[] }) {
|
||||
if (server) await server.stop(true)
|
||||
server = await Server.listen(input)
|
||||
server = await Server.listen({ type: "tcp", ...input })
|
||||
return { url: server.url.toString() }
|
||||
},
|
||||
async checkUpgrade(input: { directory: string }) {
|
||||
|
|
|
|||
|
|
@ -58,5 +58,5 @@ export function resolveNetworkOptionsNoConfig(args: NetworkOptions, config?: Con
|
|||
const argsCors = Array.isArray(args.cors) ? args.cors : args.cors ? [args.cors] : []
|
||||
const cors = [...configCors, ...argsCors]
|
||||
|
||||
return { hostname, port, mdns, mdnsDomain, cors }
|
||||
return { type: "tcp" as const, hostname, port, mdns, mdnsDomain, cors }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ type ServerApp = {
|
|||
}
|
||||
|
||||
export type TcpListenOptions = CorsOptions & {
|
||||
type?: "tcp"
|
||||
type: "tcp"
|
||||
port: number
|
||||
hostname: string
|
||||
mdns?: boolean
|
||||
|
|
@ -119,7 +119,17 @@ export async function listen(opts: ListenOptions): Promise<Listener> {
|
|||
const listenEffect: (opts: ListenOptions) => Effect.Effect<EffectListener, unknown> = Effect.fn("Server.listen")(
|
||||
function* (opts: ListenOptions) {
|
||||
const state = yield* startWithPortFallback(opts)
|
||||
if (opts.type === "socket") return yield* makeSocketListener(state, opts.socket)
|
||||
if (opts.type === "socket") {
|
||||
const listenerUrl = makeURL("localhost", 0)
|
||||
url = listenerUrl
|
||||
|
||||
return {
|
||||
type: "socket" as const,
|
||||
socket: opts.socket,
|
||||
url: listenerUrl,
|
||||
stop: yield* makeStop(state, Effect.void),
|
||||
}
|
||||
}
|
||||
|
||||
const address = yield* tcpAddress(state)
|
||||
const listenerUrl = makeURL(opts.hostname, address.port)
|
||||
|
|
@ -177,20 +187,6 @@ function startListener(opts: ListenOptions) {
|
|||
)
|
||||
}
|
||||
|
||||
function makeSocketListener(state: ListenerState, socket: string) {
|
||||
return Effect.gen(function* () {
|
||||
const listenerUrl = makeURL("localhost", 0)
|
||||
url = listenerUrl
|
||||
|
||||
return {
|
||||
type: "socket" as const,
|
||||
socket,
|
||||
url: listenerUrl,
|
||||
stop: yield* makeStop(state, Effect.void),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function tcpAddress(state: ListenerState) {
|
||||
return Effect.gen(function* () {
|
||||
if (state.server.address._tag === "TcpAddress") return state.server.address
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ describe("HttpApi CORS", () => {
|
|||
it.live("uses custom CORS origins passed to the server", () =>
|
||||
Effect.gen(function* () {
|
||||
const listener = yield* Effect.acquireRelease(
|
||||
Effect.promise(() => Server.listen({ hostname: "127.0.0.1", port: 0, cors: ["https://custom.example"] })),
|
||||
Effect.promise(() =>
|
||||
Server.listen({ type: "tcp", hostname: "127.0.0.1", port: 0, cors: ["https://custom.example"] }),
|
||||
),
|
||||
(listener) => Effect.promise(() => listener.stop(true)),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ async function startListener() {
|
|||
Flag.OPENCODE_SERVER_USERNAME = auth.username
|
||||
process.env.OPENCODE_SERVER_PASSWORD = auth.password
|
||||
process.env.OPENCODE_SERVER_USERNAME = auth.username
|
||||
return Server.listen({ hostname: "127.0.0.1", port: 0 })
|
||||
return Server.listen({ type: "tcp", hostname: "127.0.0.1", port: 0 })
|
||||
}
|
||||
|
||||
async function startNoAuthListener() {
|
||||
|
|
@ -45,7 +45,7 @@ async function startNoAuthListener() {
|
|||
Flag.OPENCODE_SERVER_USERNAME = auth.username
|
||||
delete process.env.OPENCODE_SERVER_PASSWORD
|
||||
process.env.OPENCODE_SERVER_USERNAME = auth.username
|
||||
return Server.listen({ hostname: "127.0.0.1", port: 0 })
|
||||
return Server.listen({ type: "tcp", hostname: "127.0.0.1", port: 0 })
|
||||
}
|
||||
|
||||
function authorization() {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ describe("HttpApi Server.listen mDNS", () => {
|
|||
test("skips publish for loopback hostnames", async () => {
|
||||
Flag.OPENCODE_SERVER_PASSWORD = "mdns-secret"
|
||||
Flag.OPENCODE_SERVER_USERNAME = "opencode"
|
||||
const listener = await Server.listen({ hostname: "127.0.0.1", port: 0, mdns: true })
|
||||
const listener = await Server.listen({ type: "tcp", hostname: "127.0.0.1", port: 0, mdns: true })
|
||||
try {
|
||||
expect(events.filter((e) => e.kind === "publish")).toEqual([])
|
||||
} finally {
|
||||
|
|
@ -57,7 +57,7 @@ describe("HttpApi Server.listen mDNS", () => {
|
|||
test("publishes for non-loopback hostnames and unpublishes on stop", async () => {
|
||||
Flag.OPENCODE_SERVER_PASSWORD = "mdns-secret"
|
||||
Flag.OPENCODE_SERVER_USERNAME = "opencode"
|
||||
const listener = await Server.listen({ hostname: "0.0.0.0", port: 0, mdns: true })
|
||||
const listener = await Server.listen({ type: "tcp", hostname: "0.0.0.0", port: 0, mdns: true })
|
||||
try {
|
||||
const published = events.filter((e) => e.kind === "publish")
|
||||
expect(published.length).toBe(1)
|
||||
|
|
@ -73,7 +73,7 @@ describe("HttpApi Server.listen mDNS", () => {
|
|||
test("scope finalizer unpublishes even if stop() is not called for force-close", async () => {
|
||||
Flag.OPENCODE_SERVER_PASSWORD = "mdns-secret"
|
||||
Flag.OPENCODE_SERVER_USERNAME = "opencode"
|
||||
const listener = await Server.listen({ hostname: "0.0.0.0", port: 0, mdns: true })
|
||||
const listener = await Server.listen({ type: "tcp", hostname: "0.0.0.0", port: 0, mdns: true })
|
||||
expect(events.filter((e) => e.kind === "publish").length).toBe(1)
|
||||
// Plain (graceful) stop without close=true should still unpublish.
|
||||
await withTimeout(listener.stop(), 10_000, "timed out stopping graceful mdns listener")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue