Disable proxy in read-only, enable better caching

pull/674/head
Zef Hemel 2024-01-29 09:43:56 +01:00
parent dbabba7326
commit f6f93d796f
1 changed files with 29 additions and 25 deletions

View File

@ -1,4 +1,5 @@
import { import {
Context,
cors, cors,
deleteCookie, deleteCookie,
getCookie, getCookie,
@ -112,14 +113,25 @@ export class HttpServer {
} }
// Replaces some template variables in index.html in a rather ad-hoc manner, but YOLO // Replaces some template variables in index.html in a rather ad-hoc manner, but YOLO
async renderHtmlPage(spaceServer: SpaceServer, pageName: string) { async renderHtmlPage(
spaceServer: SpaceServer,
pageName: string,
c: Context,
): Promise<Response> {
let html = ""; let html = "";
let lastModified = utcDateString(Date.now());
if (!spaceServer.auth) { if (!spaceServer.auth) {
// Only attempt server-side rendering when this site is not protected by auth // Only attempt server-side rendering when this site is not protected by auth
try { try {
const { data } = await spaceServer.spacePrimitives.readFile( const { data, meta } = await spaceServer.spacePrimitives.readFile(
`${pageName}.md`, `${pageName}.md`,
); );
lastModified = utcDateString(meta.lastModified);
if (c.req.header("If-Modified-Since") === lastModified) {
// Not modified, empty body status 304
return c.body(null, 304);
}
const text = new TextDecoder().decode(data); const text = new TextDecoder().decode(data);
const tree = parse(extendedMarkdownLanguage, text); const tree = parse(extendedMarkdownLanguage, text);
html = renderMarkdownToHtml(tree); html = renderMarkdownToHtml(tree);
@ -130,7 +142,7 @@ export class HttpServer {
} }
} }
// TODO: Replace this with a proper template engine // TODO: Replace this with a proper template engine
return this.clientAssetBundle.readTextFileSync(".client/index.html") html = this.clientAssetBundle.readTextFileSync(".client/index.html")
.replace( .replace(
"{{SPACE_PATH}}", "{{SPACE_PATH}}",
spaceServer.pagesPath.replaceAll("\\", "\\\\"), spaceServer.pagesPath.replaceAll("\\", "\\\\"),
@ -155,6 +167,13 @@ export class HttpServer {
"{{CLIENT_ENCRYPTION}}", "{{CLIENT_ENCRYPTION}}",
spaceServer.clientEncryption ? "true" : "false", spaceServer.clientEncryption ? "true" : "false",
); );
return c.html(
html,
200,
{
"Last-Modified": lastModified,
},
);
} }
start() { start() {
@ -168,9 +187,7 @@ export class HttpServer {
const spaceServer = await this.ensureSpaceServer(c.req); const spaceServer = await this.ensureSpaceServer(c.req);
const url = new URL(c.req.url); const url = new URL(c.req.url);
const pageName = decodeURI(url.pathname.slice(1)); const pageName = decodeURI(url.pathname.slice(1));
return c.html(await this.renderHtmlPage(spaceServer, pageName), 200, { return this.renderHtmlPage(spaceServer, pageName, c);
"Cache-Control": "no-cache",
});
}); });
this.abortController = new AbortController(); this.abortController = new AbortController();
@ -207,15 +224,8 @@ export class HttpServer {
url.pathname === "/" url.pathname === "/"
) { ) {
// Serve the UI (index.html) // Serve the UI (index.html)
// Note: we're explicitly not setting Last-Modified and If-Modified-Since header here because this page is dynamic
const indexPage = parsePageRef(spaceServer.settings?.indexPage!).page; const indexPage = parsePageRef(spaceServer.settings?.indexPage!).page;
return c.html( return this.renderHtmlPage(spaceServer, indexPage, c);
await this.renderHtmlPage(spaceServer, indexPage),
200,
{
"Cache-Control": "no-cache",
},
);
} }
try { try {
const assetName = url.pathname.slice(1); const assetName = url.pathname.slice(1);
@ -235,7 +245,6 @@ export class HttpServer {
let data: Uint8Array | string = this.clientAssetBundle.readFileSync( let data: Uint8Array | string = this.clientAssetBundle.readFileSync(
assetName, assetName,
); );
c.header("Cache-Control", "no-cache");
c.header("Content-length", "" + data.length); c.header("Content-length", "" + data.length);
if (assetName !== "service_worker.js") { if (assetName !== "service_worker.js") {
c.header( c.header(
@ -246,6 +255,7 @@ export class HttpServer {
if (req.method === "GET") { if (req.method === "GET") {
if (assetName === "service_worker.js") { if (assetName === "service_worker.js") {
c.header("Cache-Control", "no-cache");
const textData = new TextDecoder().decode(data); const textData = new TextDecoder().decode(data);
// console.log( // console.log(
// "Swapping out config hash in service worker", // "Swapping out config hash in service worker",
@ -384,16 +394,6 @@ export class HttpServer {
}), }),
); );
// For when the day comes...
// this.app.use("*", async (c, next) => {
// // if (["POST", "PUT", "DELETE"].includes(c.req.method)) {
// const spaceServer = await this.ensureSpaceServer(c.req);
// return runWithSystemLock(spaceServer.system!, async () => {
// await next();
// });
// // }
// });
// File list // File list
this.app.get( this.app.get(
"/index.json", "/index.json",
@ -599,6 +599,10 @@ export class HttpServer {
proxyPathRegex, proxyPathRegex,
async (c, next) => { async (c, next) => {
const req = c.req; const req = c.req;
const spaceServer = await this.ensureSpaceServer(req);
if (spaceServer.readOnly) {
return c.text("Read only mode, no federation proxy allowed", 405);
}
let url = req.param("uri")!.slice(1); let url = req.param("uri")!.slice(1);
if (!req.header("X-Proxy-Request")) { if (!req.header("X-Proxy-Request")) {
// Direct browser request, not explicity fetch proxy request // Direct browser request, not explicity fetch proxy request