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.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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-canvas.priority=100"
|
- "traefik.http.routers.rspace-canvas.priority=100"
|
||||||
# ── Standalone domain routing (priority 120) ──
|
# ── Standalone domain routing (priority 120) — redirect to rspace.online ──
|
||||||
- "traefik.http.routers.rspace-rbooks.rule=Host(`rbooks.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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rbooks.priority=120"
|
- "traefik.http.routers.rspace-rbooks.priority=120"
|
||||||
- "traefik.http.routers.rspace-rbooks.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rpubs.priority=120"
|
- "traefik.http.routers.rspace-rpubs.priority=120"
|
||||||
- "traefik.http.routers.rspace-rpubs.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rchoices.priority=120"
|
- "traefik.http.routers.rspace-rchoices.priority=120"
|
||||||
- "traefik.http.routers.rspace-rchoices.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rfunds.priority=120"
|
- "traefik.http.routers.rspace-rfunds.priority=120"
|
||||||
- "traefik.http.routers.rspace-rfunds.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rforum.priority=120"
|
- "traefik.http.routers.rspace-rforum.priority=120"
|
||||||
- "traefik.http.routers.rspace-rforum.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rvote.priority=120"
|
- "traefik.http.routers.rspace-rvote.priority=120"
|
||||||
- "traefik.http.routers.rspace-rvote.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rwork.priority=120"
|
- "traefik.http.routers.rspace-rwork.priority=120"
|
||||||
- "traefik.http.routers.rspace-rwork.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rcal.priority=120"
|
- "traefik.http.routers.rspace-rcal.priority=120"
|
||||||
- "traefik.http.routers.rspace-rcal.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rtrips.priority=120"
|
- "traefik.http.routers.rspace-rtrips.priority=120"
|
||||||
- "traefik.http.routers.rspace-rtrips.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rwallet.priority=120"
|
- "traefik.http.routers.rspace-rwallet.priority=120"
|
||||||
- "traefik.http.routers.rspace-rwallet.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rdata.priority=120"
|
- "traefik.http.routers.rspace-rdata.priority=120"
|
||||||
- "traefik.http.routers.rspace-rdata.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rnetwork.priority=120"
|
- "traefik.http.routers.rspace-rnetwork.priority=120"
|
||||||
- "traefik.http.routers.rspace-rnetwork.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rtube.priority=120"
|
- "traefik.http.routers.rspace-rtube.priority=120"
|
||||||
- "traefik.http.routers.rspace-rtube.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rmaps.priority=120"
|
- "traefik.http.routers.rspace-rmaps.priority=120"
|
||||||
- "traefik.http.routers.rspace-rmaps.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rnotes.priority=120"
|
- "traefik.http.routers.rspace-rnotes.priority=120"
|
||||||
- "traefik.http.routers.rspace-rnotes.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rfiles.priority=120"
|
- "traefik.http.routers.rspace-rfiles.priority=120"
|
||||||
- "traefik.http.routers.rspace-rfiles.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rphotos.priority=120"
|
- "traefik.http.routers.rspace-rphotos.priority=120"
|
||||||
- "traefik.http.routers.rspace-rphotos.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rinbox.priority=120"
|
- "traefik.http.routers.rspace-rinbox.priority=120"
|
||||||
- "traefik.http.routers.rspace-rinbox.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rcart.priority=120"
|
- "traefik.http.routers.rspace-rcart.priority=120"
|
||||||
- "traefik.http.routers.rspace-rcart.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rsplat.priority=120"
|
- "traefik.http.routers.rspace-rsplat.priority=120"
|
||||||
- "traefik.http.routers.rspace-rsplat.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rswag.priority=120"
|
- "traefik.http.routers.rspace-rswag.priority=120"
|
||||||
- "traefik.http.routers.rspace-rswag.service=rspace-online"
|
- "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.entrypoints=web"
|
||||||
- "traefik.http.routers.rspace-rsocials.priority=120"
|
- "traefik.http.routers.rspace-rsocials.priority=120"
|
||||||
- "traefik.http.routers.rspace-rsocials.service=rspace-online"
|
- "traefik.http.routers.rspace-rsocials.service=rspace-online"
|
||||||
|
|
|
||||||
|
|
@ -982,8 +982,22 @@ const server = Bun.serve<WSData>({
|
||||||
const hostClean = host?.split(":")[0] || "";
|
const hostClean = host?.split(":")[0] || "";
|
||||||
const subdomain = getSubdomain(host);
|
const subdomain = getSubdomain(host);
|
||||||
|
|
||||||
// ── Standalone domain → internal rewrite to module routes ──
|
// ── Standalone domain → 301 redirect to rspace.online ──
|
||||||
const standaloneModuleId = domainToModule.get(hostClean);
|
// 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) {
|
if (standaloneModuleId) {
|
||||||
// Self-fetch detection: landing proxy uses this User-Agent;
|
// Self-fetch detection: landing proxy uses this User-Agent;
|
||||||
// return 404 to break circular fetch so the generic fallback is used
|
// 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 });
|
return new Response("Not found", { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static assets pass through
|
// Determine the space and remaining path
|
||||||
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}/...
|
|
||||||
const pathParts = url.pathname.split("/").filter(Boolean);
|
const pathParts = url.pathname.split("/").filter(Boolean);
|
||||||
let space = "demo";
|
let space = standaloneSub || null; // subdomain on standalone domain = space
|
||||||
let suffix = "";
|
let remainingPath = "";
|
||||||
|
|
||||||
if (
|
if (pathParts.length > 0 && !pathParts[0].includes(".") &&
|
||||||
pathParts.length > 0 &&
|
pathParts[0] !== "api" && pathParts[0] !== "ws") {
|
||||||
!pathParts[0].includes(".") &&
|
// First path segment is the space (if no subdomain already set it)
|
||||||
pathParts[0] !== "api" &&
|
if (!space) {
|
||||||
pathParts[0] !== "ws"
|
space = pathParts[0];
|
||||||
) {
|
remainingPath = pathParts.length > 1 ? "/" + pathParts.slice(1).join("/") : "";
|
||||||
space = pathParts[0];
|
} else {
|
||||||
suffix = pathParts.length > 1 ? "/" + pathParts.slice(1).join("/") : "";
|
remainingPath = url.pathname;
|
||||||
} else if (url.pathname !== "/") {
|
}
|
||||||
suffix = url.pathname;
|
} else {
|
||||||
|
remainingPath = url.pathname === "/" ? "" : url.pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rewrittenPath = `/${space}/${standaloneModuleId}${suffix}`;
|
// Build redirect URL
|
||||||
const rewrittenUrl = new URL(rewrittenPath + url.search, `http://localhost:${PORT}`);
|
let redirectUrl: string;
|
||||||
const rewrittenReq = new Request(rewrittenUrl, req);
|
if (space) {
|
||||||
return app.fetch(rewrittenReq);
|
// 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 ──
|
// ── WebSocket upgrade ──
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue