Merge branch 'dev'
This commit is contained in:
commit
6f4befdd19
|
|
@ -51,92 +51,93 @@ services:
|
|||
- "traefik.http.routers.rspace-canvas.rule=HostRegexp(`{subdomain:[a-z0-9-]+}.rspace.online`) && !Host(`rspace.online`) && !Host(`www.rspace.online`) && !Host(`auth.rspace.online`)"
|
||||
- "traefik.http.routers.rspace-canvas.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-canvas.priority=100"
|
||||
# ── Standalone domain routing (priority 120) ──
|
||||
- "traefik.http.routers.rspace-rbooks.rule=Host(`rbooks.online`)"
|
||||
# ── Standalone domain routing (priority 120) — redirect to rspace.online ──
|
||||
# Each rule matches bare domain + any subdomain (e.g. rnotes.online, alice.rnotes.online)
|
||||
- "traefik.http.routers.rspace-rbooks.rule=Host(`rbooks.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rbooks.online`)"
|
||||
- "traefik.http.routers.rspace-rbooks.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rbooks.priority=120"
|
||||
- "traefik.http.routers.rspace-rbooks.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rpubs.rule=Host(`rpubs.online`)"
|
||||
- "traefik.http.routers.rspace-rpubs.rule=Host(`rpubs.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rpubs.online`)"
|
||||
- "traefik.http.routers.rspace-rpubs.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rpubs.priority=120"
|
||||
- "traefik.http.routers.rspace-rpubs.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rchoices.rule=Host(`rchoices.online`)"
|
||||
- "traefik.http.routers.rspace-rchoices.rule=Host(`rchoices.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rchoices.online`)"
|
||||
- "traefik.http.routers.rspace-rchoices.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rchoices.priority=120"
|
||||
- "traefik.http.routers.rspace-rchoices.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rfunds.rule=Host(`rfunds.online`)"
|
||||
- "traefik.http.routers.rspace-rfunds.rule=Host(`rfunds.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rfunds.online`)"
|
||||
- "traefik.http.routers.rspace-rfunds.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rfunds.priority=120"
|
||||
- "traefik.http.routers.rspace-rfunds.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rforum.rule=Host(`rforum.online`)"
|
||||
- "traefik.http.routers.rspace-rforum.rule=Host(`rforum.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rforum.online`)"
|
||||
- "traefik.http.routers.rspace-rforum.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rforum.priority=120"
|
||||
- "traefik.http.routers.rspace-rforum.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rvote.rule=Host(`rvote.online`)"
|
||||
- "traefik.http.routers.rspace-rvote.rule=Host(`rvote.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rvote.online`)"
|
||||
- "traefik.http.routers.rspace-rvote.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rvote.priority=120"
|
||||
- "traefik.http.routers.rspace-rvote.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rwork.rule=Host(`rwork.online`)"
|
||||
- "traefik.http.routers.rspace-rwork.rule=Host(`rwork.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rwork.online`)"
|
||||
- "traefik.http.routers.rspace-rwork.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rwork.priority=120"
|
||||
- "traefik.http.routers.rspace-rwork.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rcal.rule=Host(`rcal.online`)"
|
||||
- "traefik.http.routers.rspace-rcal.rule=Host(`rcal.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rcal.online`)"
|
||||
- "traefik.http.routers.rspace-rcal.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rcal.priority=120"
|
||||
- "traefik.http.routers.rspace-rcal.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rtrips.rule=Host(`rtrips.online`)"
|
||||
- "traefik.http.routers.rspace-rtrips.rule=Host(`rtrips.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rtrips.online`)"
|
||||
- "traefik.http.routers.rspace-rtrips.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rtrips.priority=120"
|
||||
- "traefik.http.routers.rspace-rtrips.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rwallet.rule=Host(`rwallet.online`)"
|
||||
- "traefik.http.routers.rspace-rwallet.rule=Host(`rwallet.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rwallet.online`)"
|
||||
- "traefik.http.routers.rspace-rwallet.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rwallet.priority=120"
|
||||
- "traefik.http.routers.rspace-rwallet.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rdata.rule=Host(`rdata.online`)"
|
||||
- "traefik.http.routers.rspace-rdata.rule=Host(`rdata.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rdata.online`)"
|
||||
- "traefik.http.routers.rspace-rdata.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rdata.priority=120"
|
||||
- "traefik.http.routers.rspace-rdata.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rnetwork.rule=Host(`rnetwork.online`)"
|
||||
- "traefik.http.routers.rspace-rnetwork.rule=Host(`rnetwork.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rnetwork.online`)"
|
||||
- "traefik.http.routers.rspace-rnetwork.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rnetwork.priority=120"
|
||||
- "traefik.http.routers.rspace-rnetwork.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rtube.rule=Host(`rtube.online`)"
|
||||
- "traefik.http.routers.rspace-rtube.rule=Host(`rtube.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rtube.online`)"
|
||||
- "traefik.http.routers.rspace-rtube.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rtube.priority=120"
|
||||
- "traefik.http.routers.rspace-rtube.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rmaps.rule=Host(`rmaps.online`)"
|
||||
- "traefik.http.routers.rspace-rmaps.rule=Host(`rmaps.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rmaps.online`)"
|
||||
- "traefik.http.routers.rspace-rmaps.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rmaps.priority=120"
|
||||
- "traefik.http.routers.rspace-rmaps.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rnotes.rule=Host(`rnotes.online`)"
|
||||
- "traefik.http.routers.rspace-rnotes.rule=Host(`rnotes.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rnotes.online`)"
|
||||
- "traefik.http.routers.rspace-rnotes.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rnotes.priority=120"
|
||||
- "traefik.http.routers.rspace-rnotes.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rfiles.rule=Host(`rfiles.online`)"
|
||||
- "traefik.http.routers.rspace-rfiles.rule=Host(`rfiles.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rfiles.online`)"
|
||||
- "traefik.http.routers.rspace-rfiles.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rfiles.priority=120"
|
||||
- "traefik.http.routers.rspace-rfiles.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rphotos.rule=Host(`rphotos.online`)"
|
||||
- "traefik.http.routers.rspace-rphotos.rule=Host(`rphotos.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rphotos.online`)"
|
||||
- "traefik.http.routers.rspace-rphotos.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rphotos.priority=120"
|
||||
- "traefik.http.routers.rspace-rphotos.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rinbox.rule=Host(`rinbox.online`)"
|
||||
- "traefik.http.routers.rspace-rinbox.rule=Host(`rinbox.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rinbox.online`)"
|
||||
- "traefik.http.routers.rspace-rinbox.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rinbox.priority=120"
|
||||
- "traefik.http.routers.rspace-rinbox.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rcart.rule=Host(`rcart.online`)"
|
||||
- "traefik.http.routers.rspace-rcart.rule=Host(`rcart.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rcart.online`)"
|
||||
- "traefik.http.routers.rspace-rcart.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rcart.priority=120"
|
||||
- "traefik.http.routers.rspace-rcart.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rsplat.rule=Host(`rsplat.online`)"
|
||||
- "traefik.http.routers.rspace-rsplat.rule=Host(`rsplat.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rsplat.online`)"
|
||||
- "traefik.http.routers.rspace-rsplat.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rsplat.priority=120"
|
||||
- "traefik.http.routers.rspace-rsplat.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rswag.rule=Host(`rswag.online`)"
|
||||
- "traefik.http.routers.rspace-rswag.rule=Host(`rswag.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rswag.online`)"
|
||||
- "traefik.http.routers.rspace-rswag.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rswag.priority=120"
|
||||
- "traefik.http.routers.rspace-rswag.service=rspace-online"
|
||||
- "traefik.http.routers.rspace-rsocials.rule=Host(`rsocials.online`)"
|
||||
- "traefik.http.routers.rspace-rsocials.rule=Host(`rsocials.online`) || HostRegexp(`{sub:[a-z0-9-]+}.rsocials.online`)"
|
||||
- "traefik.http.routers.rspace-rsocials.entrypoints=web"
|
||||
- "traefik.http.routers.rspace-rsocials.priority=120"
|
||||
- "traefik.http.routers.rspace-rsocials.service=rspace-online"
|
||||
|
|
|
|||
|
|
@ -982,8 +982,22 @@ const server = Bun.serve<WSData>({
|
|||
const hostClean = host?.split(":")[0] || "";
|
||||
const subdomain = getSubdomain(host);
|
||||
|
||||
// ── Standalone domain → internal rewrite to module routes ──
|
||||
const standaloneModuleId = domainToModule.get(hostClean);
|
||||
// ── Standalone domain → 301 redirect to rspace.online ──
|
||||
// Check both bare domain and subdomain variants (e.g. rnotes.online, alice.rnotes.online)
|
||||
let standaloneModuleId = domainToModule.get(hostClean);
|
||||
let standaloneSub: string | null = null;
|
||||
if (!standaloneModuleId) {
|
||||
// Check if this is a subdomain of a standalone domain (e.g. alice.rnotes.online)
|
||||
const hostParts = hostClean.split(".");
|
||||
if (hostParts.length >= 3) {
|
||||
const baseDomain = hostParts.slice(-2).join(".");
|
||||
const candidate = domainToModule.get(baseDomain);
|
||||
if (candidate) {
|
||||
standaloneModuleId = candidate;
|
||||
standaloneSub = hostParts.slice(0, -2).join(".");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (standaloneModuleId) {
|
||||
// Self-fetch detection: landing proxy uses this User-Agent;
|
||||
// return 404 to break circular fetch so the generic fallback is used
|
||||
|
|
@ -991,41 +1005,37 @@ const server = Bun.serve<WSData>({
|
|||
return new Response("Not found", { status: 404 });
|
||||
}
|
||||
|
||||
// Static assets pass through
|
||||
if (url.pathname !== "/" && !url.pathname.startsWith("/api/") && !url.pathname.startsWith("/ws/")) {
|
||||
const assetPath = url.pathname.slice(1);
|
||||
if (assetPath.includes(".")) {
|
||||
const staticResponse = await serveStatic(assetPath);
|
||||
if (staticResponse) return staticResponse;
|
||||
}
|
||||
}
|
||||
|
||||
// Root path → redirect to rspace.online/{moduleId} landing page
|
||||
if (url.pathname === "/") {
|
||||
return Response.redirect(`https://rspace.online/${standaloneModuleId}`, 302);
|
||||
}
|
||||
|
||||
// Sub-paths: rewrite internally → /{space}/{moduleId}/...
|
||||
// Determine the space and remaining path
|
||||
const pathParts = url.pathname.split("/").filter(Boolean);
|
||||
let space = "demo";
|
||||
let suffix = "";
|
||||
let space = standaloneSub || null; // subdomain on standalone domain = space
|
||||
let remainingPath = "";
|
||||
|
||||
if (
|
||||
pathParts.length > 0 &&
|
||||
!pathParts[0].includes(".") &&
|
||||
pathParts[0] !== "api" &&
|
||||
pathParts[0] !== "ws"
|
||||
) {
|
||||
space = pathParts[0];
|
||||
suffix = pathParts.length > 1 ? "/" + pathParts.slice(1).join("/") : "";
|
||||
} else if (url.pathname !== "/") {
|
||||
suffix = url.pathname;
|
||||
if (pathParts.length > 0 && !pathParts[0].includes(".") &&
|
||||
pathParts[0] !== "api" && pathParts[0] !== "ws") {
|
||||
// First path segment is the space (if no subdomain already set it)
|
||||
if (!space) {
|
||||
space = pathParts[0];
|
||||
remainingPath = pathParts.length > 1 ? "/" + pathParts.slice(1).join("/") : "";
|
||||
} else {
|
||||
remainingPath = url.pathname;
|
||||
}
|
||||
} else {
|
||||
remainingPath = url.pathname === "/" ? "" : url.pathname;
|
||||
}
|
||||
|
||||
const rewrittenPath = `/${space}/${standaloneModuleId}${suffix}`;
|
||||
const rewrittenUrl = new URL(rewrittenPath + url.search, `http://localhost:${PORT}`);
|
||||
const rewrittenReq = new Request(rewrittenUrl, req);
|
||||
return app.fetch(rewrittenReq);
|
||||
// Build redirect URL
|
||||
let redirectUrl: string;
|
||||
if (space) {
|
||||
// Space-qualified: alice.rnotes.online/path or rnotes.online/alice/path
|
||||
// → alice.rspace.online/rnotes/path
|
||||
redirectUrl = `https://${space}.rspace.online/${standaloneModuleId}${remainingPath}`;
|
||||
} else {
|
||||
// No space: rnotes.online/ or rnotes.online/api/...
|
||||
// → rspace.online/rnotes or rspace.online/rnotes/api/...
|
||||
redirectUrl = `https://rspace.online/${standaloneModuleId}${remainingPath}`;
|
||||
}
|
||||
if (url.search) redirectUrl += url.search;
|
||||
return Response.redirect(redirectUrl, 301);
|
||||
}
|
||||
|
||||
// ── WebSocket upgrade ──
|
||||
|
|
|
|||
Loading…
Reference in New Issue