Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/apps/web/app/utils/http/readLimitedRequestBody.server.test.ts
T

74 lines
3.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { readLimitedRequestBytes, readLimitedRequestFormData, RequestBodyLimitError } from "./readLimitedRequestBody.server";
describe("readLimitedRequestBytes", () => {
it("reads a bounded request body", async () => {
const request = new Request("https://app.example.test/upload", { method: "POST", body: new Uint8Array([1, 2, 3]) });
await expect(readLimitedRequestBytes(request, 3)).resolves.toEqual(new Uint8Array([1, 2, 3]));
});
it("rejects an oversized declared body before buffering", async () => {
const request = new Request("https://app.example.test/upload", {
method: "POST",
headers: { "content-length": "4" },
body: new Uint8Array([1]),
});
await expect(readLimitedRequestBytes(request, 3)).rejects.toBeInstanceOf(RequestBodyLimitError);
});
it("rejects streamed bytes when content-length is absent or understated", async () => {
for (const headers of [{}, { "content-length": "1" }]) {
const request = new Request("https://app.example.test/upload", {
method: "POST",
headers,
body: new ReadableStream({
start(controller) {
controller.enqueue(new Uint8Array([1, 2]));
controller.enqueue(new Uint8Array([3, 4]));
controller.close();
},
}),
duplex: "half",
} as RequestInit & { duplex: "half" });
await expect(readLimitedRequestBytes(request, 3)).rejects.toBeInstanceOf(RequestBodyLimitError);
}
});
});
describe("readLimitedRequestFormData", () => {
it("parses multipart form data within the streamed byte limit", async () => {
const boundary = "pilot-boundary";
const body = [
`--${boundary}\r\nContent-Disposition: form-data; name="csrf"\r\n\r\ncsrf-token\r\n`,
`--${boundary}\r\nContent-Disposition: form-data; name="message"\r\n\r\nPilot\r\n`,
`--${boundary}--\r\n`,
].join("");
const request = new Request("https://app.example.test/upload", {
method: "POST",
headers: { "content-type": `multipart/form-data; boundary=${boundary}` },
body,
});
const parsed = await readLimitedRequestFormData(request, 1024);
expect(parsed.get("csrf")).toBe("csrf-token");
expect(parsed.get("message")).toBe("Pilot");
});
it.each([undefined, "1"])("rejects actual multipart bytes when content-length is %s", async (contentLength) => {
const form = new FormData();
form.set("file", new File(["payload that exceeds the route limit"], "pilot.txt", { type: "text/plain" }));
const encoded = new Request("https://app.example.test/upload", { method: "POST", body: form });
const headers = new Headers({ "content-type": encoded.headers.get("content-type") ?? "" });
if (contentLength) headers.set("content-length", contentLength);
const request = new Request(encoded.url, {
method: "POST",
headers,
body: encoded.body,
duplex: "half",
} as RequestInit & { duplex: "half" });
await expect(readLimitedRequestFormData(request, 16)).rejects.toBeInstanceOf(RequestBodyLimitError);
});
});