123456789101112const BUCKET = "kohbucket";13const objects = new Map<string, Uint8Array>();1415async function handle(request: Request): Promise<Response> {16 const url = new URL(request.url);17 const [, bucket = "", ...rest] = url.pathname.split("/");18 if (bucket !== BUCKET) return new Response("", { status: 404 });19 if (url.searchParams.get("list-type") === "2") {20 const prefix = url.searchParams.get("prefix") ?? "";21 const delimiter = url.searchParams.get("delimiter");22 const keys = [...objects.keys()].filter((key) => key.startsWith(prefix)).sort();23 24 const folders = new Set<string>();25 const listed = keys.filter((key) => {26 const at = delimiter ? key.indexOf(delimiter, prefix.length) : -1;27 if (at >= 0) folders.add(key.slice(0, at + 1));28 return at < 0;29 });30 const contents = listed31 .map(32 (key) =>33 `<Contents><Key>${key}</Key><Size>${objects.get(key)?.length ?? 0}</Size></Contents>`,34 )35 .join("");36 const common = [...folders]37 .map((folder) => `<CommonPrefixes><Prefix>${folder}</Prefix></CommonPrefixes>`)38 .join("");39 return new Response(40 `<?xml version="1.0" encoding="UTF-8"?><ListBucketResult><IsTruncated>false</IsTruncated>${contents}${common}</ListBucketResult>`,41 { headers: { "content-type": "application/xml" } },42 );43 }44 const key = rest.join("/");45 if (request.method === "PUT") {46 const body = new Uint8Array(await request.arrayBuffer());47 if (request.headers.get("if-none-match") === "*" && objects.has(key)) {48 return new Response("", { status: 412 });49 }50 objects.set(key, body);51 return new Response("", { status: 200, headers: { etag: `"${body.length}"` } });52 }53 if (request.method === "GET" || request.method === "HEAD") {54 const body = objects.get(key);55 if (!body) return new Response("", { status: 404 });56 return new Response(request.method === "HEAD" ? null : body, {57 status: 200,58 headers: { etag: `"${body.length}"`, "content-length": String(body.length) },59 });60 }61 if (request.method === "DELETE") {62 objects.delete(key);63 return new Response("", { status: 204 });64 }65 return new Response("", { status: 404 });66}6768const server = Bun.serve({ port: 0, fetch: handle });69console.log(`http://127.0.0.1:${server.port}`);