utilize etags

This commit is contained in:
Niki Wix Skaarup 2025-04-13 19:00:44 +02:00
parent 11e5b20722
commit 432a0e1b51
Signed by: nikiskaarup
GPG key ID: FC2F1B116F6E788C

View file

@ -11,6 +11,22 @@ const development = env.NODE_ENV !== 'production';
const faviconInit = { headers: new Headers({ 'Content-Type': 'image/png' }) }; const faviconInit = { headers: new Headers({ 'Content-Type': 'image/png' }) };
function getEtag(data: string) {
const sha = Bun.SHA256.hash(data);
return Buffer.from(sha.buffer).toString('base64url');
}
function etagResponse(etag: string, cacheControl?: string) {
const headers = new Headers();
headers.set('ETag', etag);
if (cacheControl) headers.set('Cache-Control', cacheControl);
return new Response('', { status: 304, headers });
}
let entriesETag = '';
let entriesNotModified = false;
Bun.serve({ Bun.serve({
routes: { routes: {
'/': homepage, '/': homepage,
@ -26,10 +42,21 @@ Bun.serve({
async GET(req) { async GET(req) {
if (!isAuthenticated(req)) return unauthorizedResp(); if (!isAuthenticated(req)) return unauthorizedResp();
const entries = await drizzleDB.select({ id: entry.id, name: entry.name, href: entry.href, finished: entry.finished, updated_at: entry.updatedAt }).from(entry).orderBy(desc(entry.updatedAt)); if (entriesNotModified && req.headers.get('if-none-match') === entriesETag) {
return etagResponse(entriesETag);
}
return new Response(JSON.stringify(entries), { entriesNotModified = true;
headers: { 'Content-Type': 'application/json' } const entries = await drizzleDB
.select({ id: entry.id, name: entry.name, href: entry.href, finished: entry.finished, updated_at: entry.updatedAt })
.from(entry)
.orderBy(desc(entry.updatedAt));
const body = JSON.stringify(entries);
entriesETag = getEtag(body);
return new Response(body, {
headers: { 'Content-Type': 'application/json', 'ETag': entriesETag }
}); });
}, },
async PUT(req) { async PUT(req) {
@ -52,6 +79,7 @@ Bun.serve({
return new Response('Invalid data, multiple matches?', { status: 400 }); return new Response('Invalid data, multiple matches?', { status: 400 });
} }
entriesNotModified = false;
return new Response(JSON.stringify({ created }), { return new Response(JSON.stringify({ created }), {
headers: { 'Content-Type': 'application/json' } headers: { 'Content-Type': 'application/json' }
}); });
@ -82,6 +110,8 @@ Bun.serve({
await drizzleDB.update(entry).set(body).where(eq(entry.id, id)).execute(); await drizzleDB.update(entry).set(body).where(eq(entry.id, id)).execute();
let created = false; let created = false;
entriesNotModified = false;
return new Response(JSON.stringify({ created: false }), { return new Response(JSON.stringify({ created: false }), {
headers: { 'Content-Type': 'application/json' } headers: { 'Content-Type': 'application/json' }
}); });
@ -94,6 +124,7 @@ Bun.serve({
await drizzleDB.delete(entry).where(eq(entry.id, id)).execute(); await drizzleDB.delete(entry).where(eq(entry.id, id)).execute();
entriesNotModified = false;
return new Response('OK'); return new Response('OK');
}, },
}, },
@ -111,6 +142,7 @@ Bun.serve({
.where(eq(entry.id, id)) .where(eq(entry.id, id))
.execute(); .execute();
entriesNotModified = false;
return new Response('OK'); return new Response('OK');
}, },
}, },