Skip to content

Instantly share code, notes, and snippets.

@cj-praveen
Last active September 18, 2025 09:11
Show Gist options
  • Select an option

  • Save cj-praveen/cb659b27e86e8c12e27a4067b83182e6 to your computer and use it in GitHub Desktop.

Select an option

Save cj-praveen/cb659b27e86e8c12e27a4067b83182e6 to your computer and use it in GitHub Desktop.
A read-only file server
#!/usr/bin/env bun
import { stat, readdir } from "fs/promises";
import { join } from "path";
const root = process.cwd();
async function html(target, baseDir) {
const entries = await readdir(target);
return new Response(
`<!DOCTYPE html>
<html>
<head>
<title>${target}</title>
</head>
<body>
<h1>${target}</h1>
<hr>
<pre>${
entries
.map(entry => `<a href="${join(baseDir, entry)}" target="_self">${entry}</a>`)
.join("<br>")}
</pre>
<hr>
</body>
</html>`,
{
headers: {
"Content-Type": "text/html"
}
}
);
}
const server = Bun.serve({
hostname: "0.0.0.0",
port: 5050,
async fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/")
return html(root, "/");
else {
const path = decodeURI(url.pathname);
const abs_path = join(root, path);
const range = req.headers.get("range");
try {
const info = await stat(abs_path);
if (info.isFile()) {
const file = Bun.file(abs_path);
if (range) {
const [startStr, endStr] = range.replace(/bytes=/, "").split("-");
const start = parseInt(startStr, 10);
const end = endStr ? parseInt(endStr, 10) : size - 1;
const chunkSize = (end - start) + 1;
const slice = file.slice(start, end + 1);
return new Response(slice, {
status: 206,
headers: {
"Content-Range": `bytes ${start}-${end}/${info.size}`,
"Accept-Ranges": "bytes",
"Content-Length": chunkSize.toString(),
"Content-Type": file.type,
},
});
}
return new Response(file, {
headers: {
"Content-Type": file.type || "application/octet-stream"
}
});
}
else if (info.isDirectory())
return html(abs_path, path);
} catch(err) {
return new Response(err, { status: 500 });
}
}
return new Response("File not found!", { status: 404 });
}
});
console.log("Press Ctrl+C to quit!");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment