import { serve } from "bun"; // This is obviously incomplete but these are probably the most common status codes + the ones we need for testing type ValidStatusCode = 200 | 201 | 400 | 404 | 405 | 500; const defaultOpts = { type: "json", headers: { "Content-Type": "application/json", }, status: 200, }; const defaultResponseBodies = { 200: "OK", 201: "Created", 400: "Bad Request", 404: "Not Found", 405: "Method Not Allowed", 500: "Internal Server Error", } as Record; function getDefaultJSONBody(request: Request) { return { url: request.url, method: request.method, }; } function makeTestJsonResponse( request: Request, opts: ResponseInit & { type?: "plaintext" | "json" } = { status: 200, type: "json" }, body?: { [k: string | number]: any } | string, ): Response { const defaultJSONBody = getDefaultJSONBody(request); let type = opts.type || "json"; let resBody; let headers; // Setup headers if (!opts.headers) headers = new Headers(); if (!(opts.headers instanceof Headers)) headers = new Headers(opts.headers); else headers = opts.headers; switch (type) { case "json": if (typeof body === "object" && body !== null) { resBody = JSON.stringify({ ...defaultJSONBody, ...body }) as string; } else if (typeof body === "string") { resBody = JSON.stringify({ ...defaultJSONBody, data: body }) as string; } else { resBody = JSON.stringify(defaultJSONBody) as string; } // Check to set headers headers.set("Content-Type", "application/json"); break; case "plaintext": if (typeof body === "object") { if (body === null) { resBody = ""; } else { resBody = JSON.stringify(body); } } // Check to set headers headers.set("Content-Type", "text/plain"); default: } return new Response(resBody as string, { ...defaultOpts, ...opts, headers: { ...defaultOpts.headers, ...headers }, }); } export function createServer() { const server = serve({ port: 0, fetch: async req => { const { pathname, search } = new URL(req.url); const lowerPath = pathname.toLowerCase(); let response: Response; switch (lowerPath.match(/\/\w+/)?.[0] || "") { // START HTTP METHOD ROUTES case "/get": if (req.method.toUpperCase() !== "GET") { response = makeTestJsonResponse(req, { status: 405 }); break; } if (search !== "") { const params = new URLSearchParams(search); const args = {} as Record; params.forEach((v, k) => { if (!isNaN(parseInt(v))) { args[k] = parseInt(v); } else { args[k] = v; } }); response = makeTestJsonResponse(req, { status: 200 }, { args }); break; } // Normal case response = makeTestJsonResponse(req); break; case "/post": if (req.method.toUpperCase() !== "POST") { response = makeTestJsonResponse(req, { status: 405 }); break; } response = makeTestJsonResponse(req, { status: 201, type: "json" }, await req.text()); break; case "/head": if (req.method.toUpperCase() !== "HEAD") { response = makeTestJsonResponse(req, { status: 405 }); break; } response = makeTestJsonResponse(req, { status: 200 }); break; // END HTTP METHOD ROUTES case "/status": // Parse the status from URL path params: /status/200 const rawStatus = lowerPath.split("/").filter(Boolean)[1]; if (rawStatus) { const status = parseInt(rawStatus); if (!isNaN(status) && status > 100 && status < 599) { response = makeTestJsonResponse( req, { status }, { data: defaultResponseBodies[(status || 200) as ValidStatusCode] }, ); break; } } response = makeTestJsonResponse(req, { status: 400 }, { data: "Invalid status" }); break; case "/delay": const rawDelay = lowerPath.split("/").filter(Boolean)[1]; if (rawDelay) { const delay = parseInt(rawDelay); if (!isNaN(delay) && delay >= 0) { await Bun.sleep(delay * 1000); response = makeTestJsonResponse(req, { status: 200 }, { data: "Delayed" }); break; } } response = makeTestJsonResponse(req, { status: 400 }, { data: "Invalid delay" }); break; case "/headers": response = makeTestJsonResponse(req, { status: 200 }, { headers: req.headers }); break; default: response = makeTestJsonResponse(req, { status: 404 }); } return response; }, }); const { port, stop } = server; return { server, port, stop }; } n> Unnamed repository; edit this file 'description' to name the repository.
aboutsummaryrefslogtreecommitdiff
AgeCommit message (Expand)AuthorFilesLines
2023-10-09fix(AbortSignal/fetch) fix AbortSignal.timeout, fetch lock behavior and fetch...Gravatar Ciro Spaciari 29-61/+303
2023-10-09Fix npm tag for canary bun-types, againGravatar Ashcon Partovi 2-56/+10
2023-10-09Add Fedora build instructions to development.md (#6359)Gravatar otterDeveloper 1-0/+10
2023-10-09added commands (#6314)Gravatar babar 1-1/+2
2023-10-09Update README.md (#6291)Gravatar TPLJ 1-1/+1
2023-10-09docs: fixing a couple typos (#6331)Gravatar Michael Di Prisco 2-2/+2
2023-10-09fix: support uint8 exit code range (#6303)Gravatar Liz 2-2/+11
2023-10-09Fix array variables preview in debugger (#6379)Gravatar 2hu 1-1/+4
2023-10-07feat(KeyObject) (#5940)Gravatar Ciro Spaciari 106-67/+9342
2023-10-07Exclude more filesGravatar Jarred Sumner 1-1/+1
2023-10-07Exclude more filesGravatar Jarred Sumner 1-1/+2
2023-10-07Update settings.jsonGravatar Jarred Sumner 1-1/+2
2023-10-07Update settings.jsonGravatar Jarred Sumner 1-2/+3
2023-10-06fix a couple install testsGravatar Dylan Conway 1-8/+8
2023-10-06formatGravatar Dylan Conway 1-1/+2
2023-10-06Fix memory leak in fetch() (#6350)Gravatar Jarred Sumner 1-2/+0
2023-10-06[types] allow onLoad plugin callbacks to return undefined (#6346)Gravatar Silver 1-1/+1
2023-10-06docs: `file.stream()` is not a promise (#6337)Gravatar Paul Nodet 1-1/+1