fix: initialize hosted Studio behind HTTPS reverse proxies

This commit is contained in:
Clintchiz committed 2026-10-19 13:59:38 +05:30
1 parent 60467a4c05
commit 953e928b05
9 files changed
+186 -4

No files matched your search

+19 -1
View File
@@ -1,4 +1,22 @@
export const studioHelpScript = `window.addEventListener("error",function(){var s=document.getElementById("validation-state"),d=document.getElementById("diagnostics");if(s&&s.textContent==="Checking"){s.textContent="Editor could not start";if(d)d.textContent="Reload the page. If this continues, rebuild and restart the site with the latest Studio configuration. Your saved draft has not been deleted.";}});document.addEventListener("DOMContentLoaded",function(){var b=document.querySelector('[data-tab="guided"]');if(b)b.click();});`;
export const studioHelpScript = `(() => {
let failed = false;
function report() {
const state = document.getElementById("validation-state");
const diagnostics = document.getElementById("diagnostics");
if (state && state.textContent === "Checking") {
state.textContent = "Editor could not start";
if (diagnostics) diagnostics.textContent = "The editor script could not initialize. Reload the page after updating the server. Your saved draft has not been deleted.";
}
}
function fail() { failed = true; report(); }
window.addEventListener("error", fail, true);
window.addEventListener("unhandledrejection", fail);
document.addEventListener("DOMContentLoaded", () => {
if (failed) report();
const button = document.querySelector('[data-tab="guided"]');
if (button) button.click();
});
})();`;
export function addStudioGuide(html: string, configured: boolean) {
const guide = `<details open class="help"><summary><strong>How to use Design Studio</strong></summary><ol><li><strong>Describe your website.</strong> Open Guided design, enter your product and audience, then choose colors, shapes and spacing with Next.</li><li><strong>Generate and compare.</strong> Click Generate three directions, review an alternative, then choose Use reviewed proposal.</li><li><strong>Refine it.</strong> Try “make buttons square and use blue as the primary color” under Edit with words. Lock decisions you want to keep.</li><li><strong>Use it in your app.</strong> Open Review &amp; apply and export Theme config or Compiled CSS. This website previews and exports designs; it does not change your deployed app automatically.</li></ol><p>${configured ? "APIMart AI is enabled with gpt-6-luna. Generation sends your brief and current design to APIMart only when you request it." : "AI is not configured. Local presets and supported rule-based edits still work. Set APIMART_API_KEY in the server .env and restart to enable gpt-6-luna."}</p></details>`;
+43
View File
@@ -0,0 +1,43 @@
/** Use an explicit external origin, rather than trusting proxy-supplied schemes. */
export function studioRequest(
request: Request,
publicOrigin = process.env.STUDIO_PUBLIC_ORIGIN ??
"https://component.wrnexusjs.dev",
): Request | Response {
const incoming = new URL(request.url);
const configured = new URL(publicOrigin);
if (
configured.protocol !== "https:" ||
configured.username ||
configured.password ||
configured.pathname !== "/" ||
configured.search ||
configured.hash
)
throw Error(
"STUDIO_PUBLIC_ORIGIN must be an HTTPS origin without a path or credentials.",
);
const origin = request.headers.get("origin");
const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(
incoming.hostname,
);
const expected =
loopback && (!origin || origin === incoming.origin)
? incoming.origin
: configured.origin;
if (origin && origin !== expected)
return Response.json(
{ error: "Same-origin requests only." },
{ status: 403, headers: { "cache-control": "no-store" } },
);
const normalized = new Request(
new URL(incoming.pathname + incoming.search, expected),
request,
);
normalized.headers.set(
"x-forwarded-proto",
new URL(expected).protocol.slice(0, -1),
);
normalized.headers.set("host", new URL(expected).host);
return normalized;
}