tjo.space/server/server.ts
Tine 9082287ad3
All checks were successful
ci / docker (push) Successful in 4m31s
feat: cors and more headers
2024-06-11 17:57:04 +02:00

116 lines
2.7 KiB
TypeScript

import { Hono } from "https://deno.land/x/hono@v4.2.5/mod.ts";
import {
serveStatic,
logger,
cors,
etag,
secureHeaders,
cache,
} from "https://deno.land/x/hono@v4.2.5/middleware.ts";
const app = new Hono();
app.use(logger());
app.use(etag());
app.use(secureHeaders());
app.use(
cache({
cacheName: "tjo-space",
cacheControl: "public, max-age=3600",
wait: true,
}),
);
// Allow CORS for tjo.space
app.use(cors({ origin: "https://tjo.space" }));
// But, /.well-known requests from anywhere.
app.use("/.well-known/*", cors({ origin: "*" }));
// .well-known for matrix
app.get("/.well-known/matrix/client", (c) =>
c.json({
"m.homeserver": {
base_url: "https://matrix.chat.tjo.space",
server_name: "tjo.space",
},
}),
);
app.get("/.well-known/matrix/server", (c) =>
c.json({
"m.server": "matrix.chat.tjo.space:443",
}),
);
app.get("/.well-known/matrix/support", (c) =>
c.json({
contacts: [
{
matrix_id: "@tine:tjo.space",
email_address: "tine@tjo.space",
role: "m.role.admin",
},
],
}),
);
// .well-known for webfinger - tailscale
app.get("/.well-known/webfinger", (c) => {
const resource = c.req.query("resource");
if (!resource) {
c.status(400);
return c.json({ error: "Missing resource query parameter" });
}
const [scheme] = resource.split(":");
if (scheme !== "acct") {
c.status(400);
return c.json({ error: "Only acct scheme is supported" });
}
return c.json({
subject: resource,
links: [
{
rel: "http://openid.net/specs/connect/1.0/issuer",
href: `https://id.tjo.space/application/o/tailscalecom/`,
},
],
});
});
const kvCache = await Deno.openKv();
// Serve plausible analytics
app.get("/js/script.js", async (c) => {
c.header("Content-Type", "text/javascript");
// Check if we have the script cached
const cachedScript = await kvCache.get<string>(["plausible", "script"]);
if (cachedScript.value) {
return c.body(cachedScript.value);
}
const response = await fetch("https://plausible.io/js/plausible.js");
const script = await response.text();
// Cache for 24 hours if we got the script
if (response.status === 200) {
await kvCache.set(["plausible", "script"], script, {
expireIn: 1000 * 60 * 60 * 24,
});
}
return c.body(script);
});
app.post("/api/event", (c) => {
const request = new Request(c.req.raw);
request.headers.delete("Cookie");
request.headers.set(
"X-Forwarded-For",
c.req.header("X-Forwarded-For") || "unknown",
);
return fetch("https://plausible.io/api/event", request);
});
// Serve website
app.use("*", serveStatic({ root: "./web" }));
// Start server
Deno.serve({ port: 8080, hostname: "0.0.0.0" }, app.fetch);