From a25028aa30bf0f3b89a9a7c99192e1a14267fc97 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Mon, 11 Sep 2023 14:52:07 +0200 Subject: Initial commit --- bun.lockb | Bin 0 -> 2354 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 bun.lockb (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..2ab9dd9 Binary files /dev/null and b/bun.lockb differ -- cgit 1.4.1 From 51cc4389f6dc7947ee34d1b3367876941e8a8fbc Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Mon, 11 Sep 2023 19:43:06 +0200 Subject: Serve static files --- README.md | 5 +++-- bun.lockb | Bin 2354 -> 2042 bytes package.json | 2 +- src/index.ts | 12 ++++++------ test/index.test.ts | 9 ++++++++- 5 files changed, 18 insertions(+), 10 deletions(-) (limited to 'bun.lockb') diff --git a/README.md b/README.md index 3430625..34f3f42 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,9 @@ ## Goals -1. To be a near-drop-in replacement for Zola -2. More indieweb features +1. Static web server with prometheus-based analytics +2. Dynamic web server capable of generating Zola-based websites +3. More indieweb features ## Installing diff --git a/bun.lockb b/bun.lockb index 2ab9dd9..f724266 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 96a8252..d0e61be 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,6 @@ }, "type": "module", "dependencies": { - "siopao": "^0.4.0" + "serve-static-bun": "^0.5.3" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 8c0a3ba..59913b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,10 @@ -import { withHtmlLiveReload } from "bun-html-live-reload"; -import Siopao from "siopao"; +import { withHtmlLiveReload } from "bun-html-live-reload" +import serveStatic from "serve-static-bun" -const router = new Siopao(); - -router.get("/status", () => new Response("OK")); +const dir = Bun.argv.length > 2 ? Bun.argv[Bun.argv.length - 1] : "./" export default withHtmlLiveReload({ - fetch: router.fetch.bind(router), + fetch: serveStatic(dir, { + dotfiles: "allow" + }), }) diff --git a/test/index.test.ts b/test/index.test.ts index d82cb9e..8a32e47 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -4,6 +4,7 @@ import { expect, test, beforeAll, afterAll } from "bun:test" import app from "../src/index" const port = 33000; +const base = `http://localhost:${port}/`; let server: Server beforeAll(async function () { @@ -15,7 +16,13 @@ afterAll(function () { }) test("/status returns 200 OK", async function () { - const res = await fetch(`http://localhost:${port}/status`) + const res = await fetch(new URL("/status", base)) expect(res.status).toBe(200) expect(await res.text()).toBe("OK") }) + +test("/ returns 200 and says Hello world", async function () { + const res = await fetch(base) + expect(res.status).toBe(200) + expect(await res.text()).toBe("Hello world") +}) -- cgit 1.4.1 From 78439b16cc66532225e75c9aa40cf7c49cddc22d Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 12 Sep 2023 10:56:39 +0200 Subject: Read config from TOML file --- bun.lockb | Bin 2042 -> 2386 bytes package.json | 3 ++- src/config.ts | 9 +++++++++ src/index.ts | 10 ++++++++-- 4 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 src/config.ts (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index f724266..c8b2651 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index d0e61be..27f95e0 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ }, "type": "module", "dependencies": { - "serve-static-bun": "^0.5.3" + "serve-static-bun": "^0.5.3", + "toml": "^3.0.0" } } \ No newline at end of file diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..064b038 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,9 @@ +import path from "node:path"; +import fs from "node:fs"; +import toml from "toml"; + +export default function readConfig(base: string) { + const filename = path.join(base, "config.toml"); + + return toml.parse(fs.readFileSync(filename, "utf-8")); +} diff --git a/src/index.ts b/src/index.ts index 4887dd6..d8c9bf1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,16 @@ +import path from "node:path"; import { withHtmlLiveReload } from "bun-html-live-reload"; import serveStatic from "serve-static-bun"; -const dir = Bun.argv.length > 2 ? Bun.argv[Bun.argv.length - 1] : "./"; +import readConfig from "./config"; + +const base = Bun.argv.length > 2 ? Bun.argv[Bun.argv.length - 1] : "."; + +const config = readConfig(base); export default withHtmlLiveReload({ - fetch: serveStatic(dir, { + fetch: serveStatic(path.join(base, "public"), { + headers: config.extra.headers, dotfiles: "allow", }), }); -- cgit 1.4.1 From 2f6152539c540697290ec73a7c1b50b9f2db88c6 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 12 Sep 2023 16:54:29 +0200 Subject: Use own logic for static file serving --- bun.lockb | Bin 2386 -> 3923 bytes package.json | 3 ++- src/index.ts | 71 ++++++++++++++++++++++++++++++++++++++++++++++++----- test/index.test.ts | 12 ++++----- 4 files changed, 72 insertions(+), 14 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index c8b2651..e8b79d3 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 27f95e0..0eb65a3 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "homestead", "module": "src/index.ts", "devDependencies": { + "@types/contains-path": "^1.0.2", "bun-html-live-reload": "^0.1.1", "bun-types": "latest" }, @@ -10,7 +11,7 @@ }, "type": "module", "dependencies": { - "serve-static-bun": "^0.5.3", + "contains-path": "^1.0.0", "toml": "^3.0.0" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index d8c9bf1..ec1c296 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,16 +1,75 @@ import path from "node:path"; +import fs, { Stats } from "node:fs"; +import fsp from "node:fs/promises"; +import util from "node:util"; + import { withHtmlLiveReload } from "bun-html-live-reload"; -import serveStatic from "serve-static-bun"; +import containsPath from "contains-path"; import readConfig from "./config"; -const base = Bun.argv.length > 2 ? Bun.argv[Bun.argv.length - 1] : "."; +const base = "../website/"; +const publicDir = path.resolve(base, "public") + path.sep; const config = readConfig(base); +const defaultHeaders = config.extra.headers; + +function getFilename(name: string): string { + return path.join(publicDir, `${name}`); +} + +let files: Map = new Map(); + +function registerFile(pathname: string, absPath: string, stat: Stats): void { + pathname = "/" + (pathname === "." || pathname === "./" ? "" : pathname); + + if (files.get(pathname) !== undefined) { + console.warn("File already registered:", pathname); + } + files.set(pathname, { + filename: absPath, + size: stat.size, + mtime: stat.mtime.toUTCString(), + }); +} + +function walkDirectory(root: string, dir: string) { + const absDir = path.join(root, dir); + for (let pathname of fs.readdirSync(absDir)) { + const relPath = path.join(dir, pathname); + const absPath = path.join(absDir, pathname); + const stat = fs.statSync(absPath); + if (stat.isDirectory()) { + walkDirectory(root, relPath + path.sep); + } else if (stat.isFile()) { + if (pathname === "index.html") { + registerFile(path.dirname(relPath), absPath, stat); + registerFile(path.dirname(relPath) + path.sep, absPath, stat); + } + registerFile(relPath, absPath, stat); + } + } +} + +walkDirectory(publicDir, ""); export default withHtmlLiveReload({ - fetch: serveStatic(path.join(base, "public"), { - headers: config.extra.headers, - dotfiles: "allow", - }), + fetch: async function (request) { + const pathname = new URL(request.url).pathname; + if (files.has(pathname)) { + const file = files.get(pathname); + console.info("filename", file.filename); + return new Response(Bun.file(file.filename), { + headers: defaultHeaders, + status: 200, + }); + } + return new Response(Bun.file(getFilename("404.html")), { + headers: Object.assign({}, defaultHeaders, { + "cache-control": "max-age=5, no-cache", + }), + status: 404, + statusText: "Not Found", + }); + }, }); diff --git a/test/index.test.ts b/test/index.test.ts index 234bd1e..c1f5f64 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -15,14 +15,12 @@ afterAll(function () { server.stop(); }); -test("/status returns 200 OK", async function () { - const res = await fetch(new URL("/status", base)); +test("/ returns 200", async function () { + const res = await fetch(base); expect(res.status).toBe(200); - expect(await res.text()).toBe("OK"); }); -test("/ returns 200 and says Hello world", async function () { - const res = await fetch(base); - expect(res.status).toBe(200); - expect(await res.text()).toBe("Hello world"); +test("/asdf returns 404", async function () { + const res = await fetch(`${base}asdf`); + expect(res.status).toBe(404); }); -- cgit 1.4.1 From 817164e34248c559d4a883bf991e48407111473a Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 12 Sep 2023 18:09:08 +0200 Subject: Remove unused dependency --- bun.lockb | Bin 3923 -> 2002 bytes package.json | 4 +--- src/index.ts | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index e8b79d3..5ccd483 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 0eb65a3..314e9f9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "homestead", "module": "src/index.ts", "devDependencies": { - "@types/contains-path": "^1.0.2", "bun-html-live-reload": "^0.1.1", "bun-types": "latest" }, @@ -11,7 +10,6 @@ }, "type": "module", "dependencies": { - "contains-path": "^1.0.0", "toml": "^3.0.0" } -} \ No newline at end of file +} diff --git a/src/index.ts b/src/index.ts index 1b181a1..8ae1d0d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,6 @@ import fsp from "node:fs/promises"; import util from "node:util"; import { withHtmlLiveReload } from "bun-html-live-reload"; -import containsPath from "contains-path"; import readConfig from "./config"; -- cgit 1.4.1 From 37ee14f5472a9bb4688238fb89bd1d9f2658e66d Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Wed, 13 Sep 2023 09:24:11 +0200 Subject: Return precompressed files, if they exist --- bun.lockb | Bin 2002 -> 3084 bytes package.json | 2 ++ src/index.ts | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 67 insertions(+), 8 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index 5ccd483..2bb84c6 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 314e9f9..7798b26 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "homestead", "module": "src/index.ts", "devDependencies": { + "@types/mime-types": "^2.1.1", "bun-html-live-reload": "^0.1.1", "bun-types": "latest" }, @@ -10,6 +11,7 @@ }, "type": "module", "dependencies": { + "mime-types": "^2.1.35", "toml": "^3.0.0" } } diff --git a/src/index.ts b/src/index.ts index b6d0713..1616df7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,8 @@ import path from "node:path"; import fs, { Stats } from "node:fs"; import fsp from "node:fs/promises"; import { withHtmlLiveReload } from "bun-html-live-reload"; +import mime from "mime-types"; +import type { BunFile } from "bun-types"; import readConfig from "./config"; @@ -13,6 +15,8 @@ const defaultHeaders = config.extra.headers; type File = { filename: string; + handle: BunFile; + relPath: string; headers?: Record; size: number; mtime: Date; @@ -20,7 +24,12 @@ type File = { let files = new Map(); -function registerFile(pathname: string, filename: string, stat: Stats): void { +function registerFile( + path: string, + pathname: string, + filename: string, + stat: Stats, +): void { pathname = "/" + (pathname === "." || pathname === "./" ? "" : pathname); if (files.get(pathname) !== undefined) { @@ -28,6 +37,8 @@ function registerFile(pathname: string, filename: string, stat: Stats): void { } files.set(pathname, { filename, + relPath: "/" + path, + handle: Bun.file(filename), headers: pathname === "/404.html" ? Object.assign({}, defaultHeaders, { "cache-control": "no-cache" }) @@ -46,14 +57,14 @@ function walkDirectory(root: string, dir: string) { if (stat.isDirectory()) { walkDirectory(root, relPath + path.sep); } else if (stat.isFile()) { - if (pathname === "index.html") { - const dir = path.dirname(relPath); - registerFile(dir, absPath, stat); + if (pathname.startsWith("index.html")) { + const dir = relPath.replace("index.html", ""); + registerFile(relPath, dir, absPath, stat); if (dir !== ".") { - registerFile(dir + path.sep, absPath, stat); + registerFile(relPath, dir + path.sep, absPath, stat); } } - registerFile(relPath, absPath, stat); + registerFile(relPath, relPath, absPath, stat); } } } @@ -63,24 +74,41 @@ walkDirectory(publicDir, ""); async function serveFile( file: File | undefined, statusCode: number = 200, + extraHeaders: Record = {}, ): Promise { - if (file && (await fsp.exists(file.filename))) { - return new Response(Bun.file(file.filename), { + if (file && file.handle.exists()) { + return new Response(file.handle, { headers: { "last-modified": file.mtime.toUTCString(), + ...extraHeaders, ...(file.headers || defaultHeaders), }, status: statusCode, }); } else { + // TODO return encoded return serveFile(files.get("/404.html"), 404); } } +async function serveEncodedFile( + file: File | undefined, + statusCode: number = 200, + extraHeaders: Record = {}, +): Promise { + const res = await serveFile(file, statusCode, extraHeaders); + res.headers.delete("content-disposition"); + return res; +} + function parseIfModifiedSinceHeader(header: string | null): number { return header ? new Date(header).getTime() + 999 : 0; } +function getMIME(filename: string): string { + return mime.contentType(path.extname(filename)) || "text/plain"; +} + export default withHtmlLiveReload({ fetch: async function (request) { const pathname = new URL(request.url).pathname; @@ -92,6 +120,35 @@ export default withHtmlLiveReload({ ) { return new Response("", { status: 304 }); } + const encodings = (request.headers.get("accept-encoding") || "") + .split(",") + .map((x) => x.trim().toLowerCase()); + if (encodings.includes("br") && files.has(file.relPath + ".br")) { + console.log( + "Using br encoding for user agent", + request.headers.get("user-agent"), + ); + return serveEncodedFile(files.get(file.relPath + ".br"), 200, { + "content-encoding": "br", + "content-type": getMIME(file.filename), + }); + } else if ( + encodings.includes("zstd") && + files.has(file.relPath + ".zst") + ) { + return serveEncodedFile(files.get(file.relPath + ".zst"), 200, { + "content-encoding": "zstd", + "content-type": getMIME(file.filename), + }); + } else if ( + encodings.includes("gzip") && + files.has(file.relPath + ".gz") + ) { + return serveEncodedFile(files.get(file.relPath + ".gz"), 200, { + "content-encoding": "gzip", + "content-type": getMIME(file.filename), + }); + } } return serveFile(file); }, -- cgit 1.4.1 From c738123d55b8c9418a76afcbfd4480cc90de0e94 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Wed, 13 Sep 2023 10:16:53 +0200 Subject: Use bun's builtin mime logic --- bun.lockb | Bin 3084 -> 2002 bytes package.json | 2 -- src/index.ts | 11 +++-------- 3 files changed, 3 insertions(+), 10 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index 2bb84c6..5af2fa2 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 7798b26..314e9f9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "homestead", "module": "src/index.ts", "devDependencies": { - "@types/mime-types": "^2.1.1", "bun-html-live-reload": "^0.1.1", "bun-types": "latest" }, @@ -11,7 +10,6 @@ }, "type": "module", "dependencies": { - "mime-types": "^2.1.35", "toml": "^3.0.0" } } diff --git a/src/index.ts b/src/index.ts index 1616df7..4382aa4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,7 +2,6 @@ import path from "node:path"; import fs, { Stats } from "node:fs"; import fsp from "node:fs/promises"; import { withHtmlLiveReload } from "bun-html-live-reload"; -import mime from "mime-types"; import type { BunFile } from "bun-types"; import readConfig from "./config"; @@ -105,10 +104,6 @@ function parseIfModifiedSinceHeader(header: string | null): number { return header ? new Date(header).getTime() + 999 : 0; } -function getMIME(filename: string): string { - return mime.contentType(path.extname(filename)) || "text/plain"; -} - export default withHtmlLiveReload({ fetch: async function (request) { const pathname = new URL(request.url).pathname; @@ -130,7 +125,7 @@ export default withHtmlLiveReload({ ); return serveEncodedFile(files.get(file.relPath + ".br"), 200, { "content-encoding": "br", - "content-type": getMIME(file.filename), + "content-type": file.handle.type, }); } else if ( encodings.includes("zstd") && @@ -138,7 +133,7 @@ export default withHtmlLiveReload({ ) { return serveEncodedFile(files.get(file.relPath + ".zst"), 200, { "content-encoding": "zstd", - "content-type": getMIME(file.filename), + "content-type": file.handle.type, }); } else if ( encodings.includes("gzip") && @@ -146,7 +141,7 @@ export default withHtmlLiveReload({ ) { return serveEncodedFile(files.get(file.relPath + ".gz"), 200, { "content-encoding": "gzip", - "content-type": getMIME(file.filename), + "content-type": file.handle.type, }); } } -- cgit 1.4.1 From 93197c349e19f1e5b1cb5244827eab64aa4ebba4 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Wed, 13 Sep 2023 10:19:40 +0200 Subject: Remove defunct live-reload Doesn't work when serving static files --- bun.lockb | Bin 2002 -> 1630 bytes package.json | 1 - src/index.ts | 7 +++---- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index 5af2fa2..9d90bd9 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 314e9f9..354305b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "homestead", "module": "src/index.ts", "devDependencies": { - "bun-html-live-reload": "^0.1.1", "bun-types": "latest" }, "peerDependencies": { diff --git a/src/index.ts b/src/index.ts index 4382aa4..69c9b1a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,7 @@ import path from "node:path"; import fs, { Stats } from "node:fs"; import fsp from "node:fs/promises"; -import { withHtmlLiveReload } from "bun-html-live-reload"; -import type { BunFile } from "bun-types"; +import type { BunFile, Serve } from "bun"; import readConfig from "./config"; @@ -104,7 +103,7 @@ function parseIfModifiedSinceHeader(header: string | null): number { return header ? new Date(header).getTime() + 999 : 0; } -export default withHtmlLiveReload({ +export default { fetch: async function (request) { const pathname = new URL(request.url).pathname; const file = files.get(pathname); @@ -147,4 +146,4 @@ export default withHtmlLiveReload({ } return serveFile(file); }, -}); +} satisfies Serve; -- cgit 1.4.1 From 627aec8448ca075ea4bf87f85229c67a7374eac0 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Wed, 13 Sep 2023 15:55:48 +0200 Subject: Collect metrics for prometheus --- bun.lockb | Bin 1630 -> 2683 bytes package.json | 1 + src/index.ts | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index 9d90bd9..bea9f9d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 354305b..a0b6a73 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ }, "type": "module", "dependencies": { + "bun-prometheus-client": "^0.0.2", "toml": "^3.0.0" } } diff --git a/src/index.ts b/src/index.ts index ff154fa..6699a10 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import path from "node:path"; import fs, { Stats } from "node:fs"; import type { BunFile, Serve } from "bun"; +import prom from "bun-prometheus-client"; import readConfig from "./config"; @@ -22,6 +23,26 @@ type File = { mtime: Date; }; +const collectDefaultMetrics = prom.collectDefaultMetrics; +collectDefaultMetrics({ + labels: { + FLY_APP_NAME: Bun.env.FLY_APP_NAME, + FLY_ALLOC_ID: Bun.env.FLY_ALLOC_ID, + FLY_REGION: Bun.env.FLY_REGION, + }, +}); +const counters = { + requestsByStatus: new prom.Counter({ + name: "requests_by_status", + help: "Number of requests by status code", + labelNames: ["status_code"], + }), + requestsByPath: new prom.Counter({ + name: "requests_by_path", + help: "Number of requests by path", + }), +}; + let files = new Map(); function registerFile( @@ -77,6 +98,7 @@ async function serveFile( extraHeaders: Record = {}, ): Promise { if (file && (await file.handle.exists())) { + counters.requestsByStatus.inc({ status_code: statusCode }); return new Response(file.handle, { headers: { "last-modified": file.mtime.toUTCString(), @@ -86,6 +108,7 @@ async function serveFile( status: statusCode, }); } else { + counters.requestsByStatus.inc({ status_code: 404 }); // TODO return encoded return serveFile(files.get("/404.html"), 404); } @@ -105,15 +128,30 @@ function parseIfModifiedSinceHeader(header: string | null): number { return header ? new Date(header).getTime() + 999 : 0; } +Bun.serve({ + port: 9091, + fetch: async function (request) { + const pathname = new URL(request.url).pathname; + switch (pathname) { + case "/metrics": + return new Response(await prom.register.metrics()); + default: + return new Response("", { status: 404 }); + } + }, +}); + export default { fetch: async function (request) { const pathname = new URL(request.url).pathname; const file = files.get(pathname); + counters.requestsByPath.inc({ path: pathname }); if (file) { if ( parseIfModifiedSinceHeader(request.headers.get("if-modified-since")) >= file?.mtime.getTime() ) { + counters.requestsByStatus.inc({ status_code: 304 }); return new Response("", { status: 304, headers: defaultHeaders }); } const encodings = (request.headers.get("accept-encoding") || "") -- cgit 1.4.1 From 7bb417f923bdaac08d0d48ef1df6d191e5030bd6 Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Thu, 14 Sep 2023 12:07:05 +0200 Subject: Catch errors and log to sentry --- bun.lockb | Bin 2683 -> 7240 bytes package.json | 1 + src/index.ts | 82 +++++++++++++++++++++++++++++++++-------------------------- 3 files changed, 47 insertions(+), 36 deletions(-) (limited to 'bun.lockb') diff --git a/bun.lockb b/bun.lockb index bea9f9d..2608647 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index f51b68d..acb0224 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "type": "module", "dependencies": { + "@sentry/node": "^7.69.0", "bun-prometheus-client": "^0.0.2", "toml": "^3.0.0" } diff --git a/src/index.ts b/src/index.ts index f968fda..d979f43 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,13 @@ import path from "node:path"; import fs, { Stats } from "node:fs"; import type { BunFile, Serve } from "bun"; +import * as Sentry from "@sentry/node"; import prom from "bun-prometheus-client"; import readConfig from "./config"; +Sentry.init({}); + const base = "./website/"; const publicDir = path.resolve(base, "public") + path.sep; @@ -148,44 +151,51 @@ console.info( const server = Bun.serve({ fetch: async function (request) { - const pathname = new URL(request.url).pathname; - const file = files.get(pathname); - counters.requestsByPath.inc({ path: pathname }); - if (file) { - if ( - parseIfModifiedSinceHeader(request.headers.get("if-modified-since")) >= - file?.mtime.getTime() - ) { - counters.requestsByStatus.inc({ status_code: 304 }); - return new Response("", { status: 304, headers: defaultHeaders }); - } - const encodings = (request.headers.get("accept-encoding") || "") - .split(",") - .map((x) => x.trim().toLowerCase()); - if (encodings.includes("br") && files.has(file.relPath + ".br")) { - return serveEncodedFile(files.get(file.relPath + ".br"), 200, { - "content-encoding": "br", - "content-type": file.handle.type, - }); - } else if ( - encodings.includes("zstd") && - files.has(file.relPath + ".zst") - ) { - return serveEncodedFile(files.get(file.relPath + ".zst"), 200, { - "content-encoding": "zstd", - "content-type": file.handle.type, - }); - } else if ( - encodings.includes("gzip") && - files.has(file.relPath + ".gz") - ) { - return serveEncodedFile(files.get(file.relPath + ".gz"), 200, { - "content-encoding": "gzip", - "content-type": file.handle.type, - }); + try { + const pathname = new URL(request.url).pathname; + const file = files.get(pathname); + counters.requestsByPath.inc({ path: pathname }); + if (file) { + if ( + parseIfModifiedSinceHeader( + request.headers.get("if-modified-since"), + ) >= file?.mtime.getTime() + ) { + counters.requestsByStatus.inc({ status_code: 304 }); + return new Response("", { status: 304, headers: defaultHeaders }); + } + const encodings = (request.headers.get("accept-encoding") || "") + .split(",") + .map((x) => x.trim().toLowerCase()); + if (encodings.includes("br") && files.has(file.relPath + ".br")) { + return serveEncodedFile(files.get(file.relPath + ".br"), 200, { + "content-encoding": "br", + "content-type": file.handle.type, + }); + } else if ( + encodings.includes("zstd") && + files.has(file.relPath + ".zst") + ) { + return serveEncodedFile(files.get(file.relPath + ".zst"), 200, { + "content-encoding": "zstd", + "content-type": file.handle.type, + }); + } else if ( + encodings.includes("gzip") && + files.has(file.relPath + ".gz") + ) { + return serveEncodedFile(files.get(file.relPath + ".gz"), 200, { + "content-encoding": "gzip", + "content-type": file.handle.type, + }); + } } + return serveFile(file); + } catch (error) { + counters.requestsByStatus.inc({ status_code: 503 }); + Sentry.captureException(error); + return new Response("Something went wrong", { status: 503 }); } - return serveFile(file); }, }); -- cgit 1.4.1