fix: mixed content on bare-domain API calls + SSE stream error handling
Two fixes:
1. Bare-domain routing used url.protocol (always http: behind TLS
termination) for redirects, causing mixed-content blocks. Added
proto helper that uses https: on production domains. Also rewrite
/{space}/api/... calls internally instead of redirecting to the
subdomain.
2. rDesign SSE stream reader now catches QUIC protocol errors on
stream close gracefully.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
50c003e8e3
commit
6e4d1436e0
|
|
@ -2769,6 +2769,8 @@ const server = Bun.serve<WSData>({
|
|||
const host = req.headers.get("host");
|
||||
const hostClean = host?.split(":")[0] || "";
|
||||
const subdomain = getSubdomain(host);
|
||||
// TLS is terminated by Cloudflare/Traefik — url.protocol is always http: internally
|
||||
const proto = hostClean.includes("rspace.online") || hostClean.includes(".online") ? "https:" : url.protocol;
|
||||
|
||||
// ── Standalone domain → 301 redirect to rspace.online ──
|
||||
// Check both bare domain and subdomain variants (e.g. rnotes.online, alice.rnotes.online)
|
||||
|
|
@ -3007,7 +3009,7 @@ const server = Bun.serve<WSData>({
|
|||
console.error(`[Template] On-demand seed failed for "${subdomain}":`, e);
|
||||
}
|
||||
const withoutTemplate = pathSegments.slice(0, -1).join("/");
|
||||
return Response.redirect(`${url.protocol}//${url.host}/${withoutTemplate}`, 302);
|
||||
return Response.redirect(`${proto}//${url.host}/${withoutTemplate}`, 302);
|
||||
}
|
||||
|
||||
// Demo route: /{moduleId}/demo → rewrite to /demo/{moduleId}
|
||||
|
|
@ -3103,16 +3105,24 @@ const server = Bun.serve<WSData>({
|
|||
return app.fetch(rewrittenReq);
|
||||
}
|
||||
|
||||
// rspace.online/{space}/{...} → redirect to {space}.rspace.online/{...}
|
||||
// (space is not a module ID — it's a space slug, canonicalize to subdomain)
|
||||
// Skip redirect for known server paths (api, admin, etc.)
|
||||
// rspace.online/{space}/{...} → handle space-prefixed paths
|
||||
// (space is not a module ID — it's a space slug)
|
||||
// Skip for known server paths (api, admin, etc.)
|
||||
const serverPaths = new Set(["api", "admin", "admin-data", "admin-action", ".well-known"]);
|
||||
if (!knownModuleIds.has(firstSegment) && !serverPaths.has(firstSegment) && pathSegments.length >= 2) {
|
||||
const secondSeg = pathSegments[1]?.toLowerCase();
|
||||
const isApiCall = secondSeg === "api" || pathSegments.some((s, i) => i >= 1 && s === "api");
|
||||
if (isApiCall) {
|
||||
// API calls: rewrite internally (avoid redirect + mixed-content)
|
||||
const rewrittenUrl = new URL(url.pathname + url.search, `http://localhost:${PORT}`);
|
||||
return app.fetch(new Request(rewrittenUrl, req));
|
||||
}
|
||||
// Page navigation: redirect to canonical subdomain URL
|
||||
const space = firstSegment;
|
||||
const rest = "/" + pathSegments.slice(1).join("/");
|
||||
const baseDomain = hostClean.replace(/^www\./, "");
|
||||
return Response.redirect(
|
||||
`${url.protocol}//${space}.${baseDomain}${rest}${url.search}`, 301
|
||||
`${proto}//${space}.${baseDomain}${rest}${url.search}`, 301
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue