openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
73 lines (72 loc) • 4.32 kB
JavaScript
import { t as escapeHtml } from "./html-escape-BMD_QFeA.mjs";
import { n as isReadHttpMethod, r as respondNotFound } from "./control-ui-http-utils-CpDIFFwm.mjs";
import { t as parseControlUiSessionPath } from "./parse-DZmn_dwe.mjs";
import { TLSSocket } from "node:tls";
//#region src/gateway/control-ui-share.ts
/** This namespace contains only public preview documents and their static card. */
function isControlUiSharePath(pathname, basePath) {
return pathname === `${basePath}/share` || pathname.startsWith(`${basePath}/share/`);
}
function serveControlUiShareDocument(req, res, url, basePath, publicOrigin) {
const targetPath = url.pathname.slice(`${basePath}/share`.length);
const session = parseControlUiSessionPath(targetPath);
if (!isReadHttpMethod(req.method) || url.href.length > 8192 || !session) {
respondNotFound(res);
return;
}
const origin = resolveControlUiShareOrigin(req, publicOrigin);
if (!origin) {
respondNotFound(res);
return;
}
const search = new URLSearchParams();
const catalogRouting = [
"catalog",
"host",
"thread"
].map((key) => [key, url.searchParams.get(key)]);
if (catalogRouting.every(([, value]) => value)) {
for (const [key, value] of catalogRouting) if (value) search.set(key, value);
}
const suffix = search.size ? `?${search}` : "";
const target = escapeHtml(`${basePath}${targetPath}${suffix}`);
const canonical = escapeHtml(`${origin}${url.pathname}${suffix}`);
const image = escapeHtml(`${origin}${basePath}/share/card.png`);
const title = session.namespace === "dashboard" ? "OpenClaw dashboard" : "OpenClaw session";
const description = "Open this shared link in OpenClaw. Access to the session is required.";
const body = `
<html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>${title}</title><meta name="robots" content="noindex, nofollow">
<meta property="og:type" content="website"><meta property="og:site_name" content="OpenClaw">
<meta property="og:title" content="${title}"><meta property="og:description" content="${description}">
<meta property="og:url" content="${canonical}"><meta property="og:image" content="${image}">
<meta property="og:image:type" content="image/png"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630">
<meta property="og:image:alt" content="OpenClaw logo and lobster mascot">
<meta name="twitter:card" content="summary_large_image">
<style>
:root{color-scheme:dark;font-family:system-ui,sans-serif;background:#0b1016;color:#f5f7fa}
body{margin:0;min-height:100svh;display:grid;place-items:center}main{width:min(680px,calc(100% - 40px));padding:40px 0}
img{display:block;width:100%;height:auto;border-radius:20px}h1{font-size:clamp(28px,5vw,40px);letter-spacing:-.04em;margin:28px 0 12px}
p{color:#b2bdc9;line-height:1.6;margin:0 0 28px}a{display:inline-block;border-radius:12px;padding:14px 22px;background:#ff5c50;color:#160b0a;font-weight:700;text-decoration:none}
a:focus-visible{outline:3px solid #fff;outline-offset:5px}
</style></head><body><main>
<img src="${image}" width="1200" height="630" alt="OpenClaw logo and lobster mascot">
<h1>${title}</h1><p>${description}</p><a href="${target}">Open ${title === "OpenClaw dashboard" ? "dashboard" : "session"}</a>
</main></body></html>`;
res.statusCode = 200;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.setHeader("Content-Security-Policy", "default-src 'none'; img-src 'self'; style-src 'unsafe-inline'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'");
res.setHeader("Cache-Control", "no-store");
res.setHeader("X-Robots-Tag", "noindex, nofollow");
res.setHeader("Content-Length", Buffer.byteLength(body));
res.end(req.method === "HEAD" ? void 0 : body);
}
function resolveControlUiShareOrigin(req, publicOrigin) {
const protocol = req.socket instanceof TLSSocket ? "https" : "http";
const address = URL.parse(publicOrigin ?? `${protocol}://${req.headers.host}`);
if (!address || !/^https?:$/u.test(address.protocol) || address.username || address.password || address.pathname !== "/" || address.search || address.hash) return null;
return address.origin;
}
//#endregion
export { resolveControlUiShareOrigin as n, serveControlUiShareDocument as r, isControlUiSharePath as t };