1
0

HTTP Caching

This commit is contained in:
Zef Hemel 2022-10-21 16:56:46 +02:00
parent 09b20cadd8
commit dc32ca81a9
4 changed files with 40 additions and 12 deletions

View File

@ -3,6 +3,7 @@ import { FileMeta } from "../types.ts";
import { FileData, FileEncoding, SpacePrimitives } from "./space_primitives.ts"; import { FileData, FileEncoding, SpacePrimitives } from "./space_primitives.ts";
import { AssetBundle } from "../../plugos/asset_bundle/bundle.ts"; import { AssetBundle } from "../../plugos/asset_bundle/bundle.ts";
const bootTime = Date.now();
export class AssetBundlePlugSpacePrimitives implements SpacePrimitives { export class AssetBundlePlugSpacePrimitives implements SpacePrimitives {
constructor( constructor(
private wrapped: SpacePrimitives, private wrapped: SpacePrimitives,
@ -16,7 +17,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives {
.map((p) => ({ .map((p) => ({
name: p, name: p,
contentType: "application/json", contentType: "application/json",
lastModified: 0, lastModified: bootTime,
perm: "ro", perm: "ro",
size: -1, size: -1,
} as FileMeta)).concat(l); } as FileMeta)).concat(l);
@ -32,7 +33,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives {
return Promise.resolve({ return Promise.resolve({
data: encoding === "string" ? new TextDecoder().decode(data) : data, data: encoding === "string" ? new TextDecoder().decode(data) : data,
meta: { meta: {
lastModified: 0, lastModified: bootTime,
size: data.byteLength, size: data.byteLength,
perm: "ro", perm: "ro",
contentType: "application/json", contentType: "application/json",
@ -46,7 +47,7 @@ export class AssetBundlePlugSpacePrimitives implements SpacePrimitives {
if (this.assetBundle.has(name)) { if (this.assetBundle.has(name)) {
const data = this.assetBundle.readFileSync(name); const data = this.assetBundle.readFileSync(name);
return Promise.resolve({ return Promise.resolve({
lastModified: 0, lastModified: bootTime,
size: data.byteLength, size: data.byteLength,
perm: "ro", perm: "ro",
contentType: "application/json", contentType: "application/json",

View File

@ -5,12 +5,13 @@ import type {
import { renderToText, replaceNodesMatching } from "$sb/lib/tree.ts"; import { renderToText, replaceNodesMatching } from "$sb/lib/tree.ts";
import type { FileMeta } from "../../common/types.ts"; import type { FileMeta } from "../../common/types.ts";
import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts"; import { parseMarkdown } from "$sb/silverbullet-syscall/markdown.ts";
import { base64EncodedDataUrl } from "../../plugos/asset_bundle/base64.ts";
const pagePrefix = "💭 "; const pagePrefix = "💭 ";
export async function readFileCloud( export async function readFileCloud(
name: string, name: string,
_encoding: FileEncoding, encoding: FileEncoding,
): Promise<{ data: FileData; meta: FileMeta } | undefined> { ): Promise<{ data: FileData; meta: FileMeta } | undefined> {
const originalUrl = name.substring( const originalUrl = name.substring(
pagePrefix.length, pagePrefix.length,
@ -36,10 +37,15 @@ export async function readFileCloud(
console.error("ERROR", e.message); console.error("ERROR", e.message);
text = e.message; text = e.message;
} }
text = await translateLinksWithPrefix(
text,
`${pagePrefix}${originalUrl.split("/")[0]}/`,
);
console.log("Got this", text);
return { return {
data: await translateLinksWithPrefix( data: encoding === "string" ? text : base64EncodedDataUrl(
text, "text/markdown",
`${pagePrefix}${originalUrl.split("/")[0]}/`, new TextEncoder().encode(text),
), ),
meta: { meta: {
name, name,

View File

@ -228,11 +228,12 @@ export async function reindexSpace() {
} }
export async function clearPageIndex(page: string) { 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); await index.clearPageIndexForPage(page);
} }
export async function parseIndexTextRepublish({ name, text }: IndexEvent) { export async function parseIndexTextRepublish({ name, text }: IndexEvent) {
console.log("Reindexing", name);
await events.dispatchEvent("page:index", { await events.dispatchEvent("page:index", {
name, name,
tree: await markdown.parseMarkdown(text), tree: await markdown.parseMarkdown(text),

View File

@ -215,16 +215,26 @@ export class HttpServer {
// Serve static files (javascript, css, html) // Serve static files (javascript, css, html)
this.app.use(async ({ request, response }, next) => { this.app.use(async ({ request, response }, next) => {
if (request.url.pathname === "/") { if (request.url.pathname === "/") {
if (request.headers.get("If-Modified-Since") === staticLastModified) {
response.status = 304;
return;
}
response.headers.set("Content-type", "text/html"); response.headers.set("Content-type", "text/html");
response.body = this.assetBundle.readTextFileSync( response.body = this.assetBundle.readTextFileSync(
"web/index.html", "web/index.html",
); );
response.headers.set("Last-Modified", staticLastModified); response.headers.set("Last-Modified", staticLastModified);
response.headers.set("ETag", await etag.calculate(response.body));
return; return;
} }
try { try {
const assetName = `web${request.url.pathname}`; 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.status = 200;
response.headers.set( response.headers.set(
"Content-type", "Content-type",
@ -233,9 +243,9 @@ export class HttpServer {
const data = this.assetBundle.readFileSync( const data = this.assetBundle.readFileSync(
assetName, assetName,
); );
response.headers.set("Cache-Control", "no-cache");
response.headers.set("Content-length", "" + data.length); response.headers.set("Content-length", "" + data.length);
response.headers.set("Last-Modified", staticLastModified); response.headers.set("Last-Modified", staticLastModified);
response.headers.set("ETag", await etag.calculate(data));
if (request.method === "GET") { if (request.method === "GET") {
response.body = data; response.body = data;
@ -299,7 +309,7 @@ export class HttpServer {
}); });
fsRouter fsRouter
.get("\/(.+)", async ({ params, response }) => { .get("\/(.+)", async ({ params, response, request }) => {
const name = params[0]; const name = params[0];
console.log("Loading file", name); console.log("Loading file", name);
try { try {
@ -307,12 +317,23 @@ export class HttpServer {
name, name,
"arraybuffer", "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.status = 200;
response.headers.set( response.headers.set(
"X-Last-Modified", "X-Last-Modified",
"" + attachmentData.meta.lastModified, "" + attachmentData.meta.lastModified,
); );
response.headers.set("Cache-Control", "no-cache");
response.headers.set("X-Permission", attachmentData.meta.perm); response.headers.set("X-Permission", attachmentData.meta.perm);
response.headers.set(
"Last-Modified",
lastModifiedHeader,
);
response.headers.set("Content-Type", attachmentData.meta.contentType); response.headers.set("Content-Type", attachmentData.meta.contentType);
response.body = attachmentData.data as ArrayBuffer; response.body = attachmentData.data as ArrayBuffer;
} catch { } catch {
@ -343,7 +364,6 @@ export class HttpServer {
response.body = "Write failed"; response.body = "Write failed";
console.error("Pipeline failed", err); console.error("Pipeline failed", err);
} }
console.log("Done with put", name);
}) })
.options("\/(.+)", async ({ response, params }) => { .options("\/(.+)", async ({ response, params }) => {
const name = params[0]; const name = params[0];