diff --git a/common/spaces/asset_bundle_space_primitives.ts b/common/spaces/asset_bundle_space_primitives.ts index 03091dc..3d80792 100644 --- a/common/spaces/asset_bundle_space_primitives.ts +++ b/common/spaces/asset_bundle_space_primitives.ts @@ -3,6 +3,7 @@ import { FileMeta } from "../types.ts"; import { FileData, FileEncoding, SpacePrimitives } from "./space_primitives.ts"; import { AssetBundle } from "../../plugos/asset_bundle/bundle.ts"; +const bootTime = Date.now(); export class AssetBundlePlugSpacePrimitives implements SpacePrimitives { constructor( private wrapped: SpacePrimitives, @@ -16,7 +17,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives { .map((p) => ({ name: p, contentType: "application/json", - lastModified: 0, + lastModified: bootTime, perm: "ro", size: -1, } as FileMeta)).concat(l); @@ -32,7 +33,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives { return Promise.resolve({ data: encoding === "string" ? new TextDecoder().decode(data) : data, meta: { - lastModified: 0, + lastModified: bootTime, size: data.byteLength, perm: "ro", contentType: "application/json", @@ -46,7 +47,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives { if (this.assetBundle.has(name)) { const data = this.assetBundle.readFileSync(name); return Promise.resolve({ - lastModified: 0, + lastModified: bootTime, size: data.byteLength, perm: "ro", contentType: "application/json", diff --git a/plugs/core/cloud.ts b/plugs/core/cloud.ts index 3554343..a6ae632 100644 --- a/plugs/core/cloud.ts +++ b/plugs/core/cloud.ts @@ -5,12 +5,13 @@ import type { import { renderToText, replaceNodesMatching } from "$sb/lib/tree.ts"; import type { FileMeta } from "../../common/types.ts"; import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; +import { base64EncodedDataUrl } from "../../plugos/asset_bundle/base64.ts"; const pagePrefix = "💭 "; export async function readFileCloud( name: string, - _encoding: FileEncoding, + encoding: FileEncoding, ): Promise<{ data: FileData; meta: FileMeta } | undefined> { const originalUrl = name.substring( pagePrefix.length, @@ -36,10 +37,15 @@ export async function readFileCloud( console.error("ERROR", e.message); text = e.message; } + text = await translateLinksWithPrefix( + text, + `${pagePrefix}${originalUrl.split("/")[0]}/`, + ); + console.log("Got this", text); return { - data: await translateLinksWithPrefix( - text, - `${pagePrefix}${originalUrl.split("/")[0]}/`, + data: encoding === "string" ? text : base64EncodedDataUrl( + "text/markdown", + new TextEncoder().encode(text), ), meta: { name, diff --git a/plugs/core/page.ts b/plugs/core/page.ts index 343dc7c..67fa561 100644 --- a/plugs/core/page.ts +++ b/plugs/core/page.ts @@ -228,11 +228,12 @@ export async function reindexSpace() { } export async function clearPageIndex(page: string) { - console.log("Clearing page index for page", page); + // console.log("Clearing page index for page", page); await index.clearPageIndexForPage(page); } export async function parseIndexTextRepublish({ name, text }: IndexEvent) { + console.log("Reindexing", name); await events.dispatchEvent("page:index", { name, tree: await markdown.parseMarkdown(text), diff --git a/server/http_server.ts b/server/http_server.ts index 3a69706..b48ae97 100644 --- a/server/http_server.ts +++ b/server/http_server.ts @@ -215,16 +215,26 @@ export class HttpServer { // Serve static files (javascript, css, html) this.app.use(async ({ request, response }, next) => { if (request.url.pathname === "/") { + if (request.headers.get("If-Modified-Since") === staticLastModified) { + response.status = 304; + return; + } response.headers.set("Content-type", "text/html"); response.body = this.assetBundle.readTextFileSync( "web/index.html", ); response.headers.set("Last-Modified", staticLastModified); - response.headers.set("ETag", await etag.calculate(response.body)); return; } try { const assetName = `web${request.url.pathname}`; + if ( + this.assetBundle.has(assetName) && + request.headers.get("If-Modified-Since") === staticLastModified + ) { + response.status = 304; + return; + } response.status = 200; response.headers.set( "Content-type", @@ -233,9 +243,9 @@ export class HttpServer { const data = this.assetBundle.readFileSync( assetName, ); + response.headers.set("Cache-Control", "no-cache"); response.headers.set("Content-length", "" + data.length); response.headers.set("Last-Modified", staticLastModified); - response.headers.set("ETag", await etag.calculate(data)); if (request.method === "GET") { response.body = data; @@ -299,7 +309,7 @@ export class HttpServer { }); fsRouter - .get("\/(.+)", async ({ params, response }) => { + .get("\/(.+)", async ({ params, response, request }) => { const name = params[0]; console.log("Loading file", name); try { @@ -307,12 +317,23 @@ export class HttpServer { name, "arraybuffer", ); + const lastModifiedHeader = new Date(attachmentData.meta.lastModified) + .toUTCString(); + if (request.headers.get("If-Modified-Since") === lastModifiedHeader) { + response.status = 304; + return; + } response.status = 200; response.headers.set( "X-Last-Modified", "" + attachmentData.meta.lastModified, ); + response.headers.set("Cache-Control", "no-cache"); response.headers.set("X-Permission", attachmentData.meta.perm); + response.headers.set( + "Last-Modified", + lastModifiedHeader, + ); response.headers.set("Content-Type", attachmentData.meta.contentType); response.body = attachmentData.data as ArrayBuffer; } catch { @@ -343,7 +364,6 @@ export class HttpServer { response.body = "Write failed"; console.error("Pipeline failed", err); } - console.log("Done with put", name); }) .options("\/(.+)", async ({ response, params }) => { const name = params[0];