This commit is contained in:
Corey Johnson 2025-07-10 16:14:18 -07:00
parent 527ecf6146
commit d6b845e6d2

View File

@ -1,47 +1,123 @@
import { startSubdomainServers } from "@/orchestrator"
import { nanoRemix } from "@workshop/nano-remix"
import { serve } from "bun"
import { join } from "node:path"
const portMap = await startSubdomainServers()
/**
* Password-protected subdomain proxy server
*
* How it works:
* 1. Starts multiple subdomain servers on different ports (3001+)
* 2. Main server (port 3000) acts as a proxy that routes requests based on subdomain
* 3. All requests are protected with Basic HTTP auth + persistent cookies
* 4. Once authenticated, cookies work across all subdomains (*.yourdomain.com)
*
* This server is designed to be run in production with NODE_ENV=production. On development,
* it allows unauthenticated access because YOLO.
*/
const server = serve({
port: 3000,
fetch: async (req) => {
const url = new URL(req.url)
const hostname = url.hostname
const serve = async () => {
const portMap = await startSubdomainServers()
const server = startServer(portMap)
logServerInfo(server, portMap)
}
const subdomain = hostname.split(".")[0]
serve()
const targetPort = subdomain && portMap[subdomain]
if (!targetPort) {
const routePath = join(import.meta.dir, "routes")
return nanoRemix(req, { routePath })
const startServer = (portMap: Record<string, number>) => {
const server = Bun.serve({
port: 3000,
routes: {
// Handle main site routes through nano-remix
"/*": requireAuth(async (req) => {
const url = new URL(req.url)
const hostname = url.hostname
const subdomain = hostname.split(".")[0]
const targetPort = subdomain && portMap[subdomain]
if (!targetPort) {
const routePath = join(import.meta.dir, "routes")
return nanoRemix(req, { routePath })
}
try {
const target = `http://127.0.0.1:${targetPort}${url.pathname}${url.search}`
// Forward the request with auth headers preserved
const forwardedReq = new Request(target, {
method: req.method,
headers: req.headers,
body: req.body,
})
const upstream = await fetch(forwardedReq)
return new Response(upstream.body, {
status: upstream.status,
headers: new Headers(upstream.headers),
})
} catch (error) {
console.error(`Error forwarding request to subdomain "${subdomain}":`, error)
return new Response(`Failed to forward request to "${subdomain}"`, { status: 500 })
}
}),
},
})
return server
}
const logServerInfo = (server: Bun.Server, portMap: Record<string, number>) => {
console.log(`${server.url}`)
const subdomainEntries = Object.entries(portMap)
subdomainEntries.forEach(([subdomain, port], index) => {
const subdomainUrl = new URL(server.url)
subdomainUrl.hostname = `${subdomain}.${subdomainUrl.hostname}`
subdomainUrl.port = port.toString()
const isLast = index === subdomainEntries.length - 1
const prefix = isLast ? "└─" : "├─"
console.log(`${prefix} ${subdomainUrl}`)
})
console.log("")
}
const requireAuth = (handler: (req: Request) => Response | Promise<Response>) => {
return async (req: Request) => {
if (process.env.NODE_ENV !== "production") {
return handler(req)
}
try {
const target = `http://127.0.0.1:${targetPort}${url.pathname}${url.search}`
const upstream = await fetch(target, req)
const cookies = new Bun.CookieMap(req.headers.get("cookie") ?? "")
if (cookies.get("auth") === "authenticated") {
return handler(req)
}
return new Response(upstream.body, {
status: upstream.status,
headers: new Headers(upstream.headers),
const auth = req.headers.get("authorization")
const correctAuth = `Basic ${btoa("spike:888")}`
if (auth === correctAuth) {
const response = await handler(req)
const newHeaders = new Headers(response.headers)
const url = new URL(req.url)
const cookieDomain = `.${url.hostname.split(".").slice(-2).join(".")}`
const authCookie = new Bun.Cookie({
name: "auth",
value: "authenticated",
domain: cookieDomain,
path: "/",
maxAge: 86400,
httpOnly: true,
})
} catch (error) {
console.error(`Error forwarding request to subdomain "${subdomain}":`, error)
return new Response(`Failed to forward request to "${subdomain}"`, { status: 500 })
}
},
})
console.log(`${server.url}`)
const subdomainEntries = Object.entries(portMap)
subdomainEntries.forEach(([subdomain, port], index) => {
const subdomainUrl = new URL(server.url)
subdomainUrl.hostname = `${subdomain}.${subdomainUrl.hostname}`
subdomainUrl.port = port.toString()
const isLast = index === subdomainEntries.length - 1
const prefix = isLast ? "└─" : "├─"
console.log(`${prefix} ${subdomainUrl}`)
})
console.log("")
newHeaders.set("Set-Cookie", authCookie.toString())
return new Response(response.body, { status: response.status, headers: newHeaders })
}
return new Response("Unauthorized", {
status: 401,
headers: { "WWW-Authenticate": 'Basic realm="Workshop Access"' },
})
}
}