diff options
Diffstat (limited to 'test/http-test-server.ts')
| -rw-r--r-- | test/http-test-server.ts | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/test/http-test-server.ts b/test/http-test-server.ts new file mode 100644 index 000000000..ab85a5ec8 --- /dev/null +++ b/test/http-test-server.ts @@ -0,0 +1,168 @@ +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<ValidStatusCode, string>; + +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<string, string | number>; + 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 }; +} |
