This commit is contained in:
Anaïs Saraiva
2026-03-29 18:45:25 +02:00
parent 0f7d692d12
commit afc839d43d
42 changed files with 3809 additions and 58 deletions
+77
View File
@@ -0,0 +1,77 @@
import { config } from "./config";
import { HttpError, isHttpError } from "./errors";
import { buildResponseHeaders } from "./security";
export const jsonResponse = (request: Request, status: number, payload: unknown, init?: HeadersInit): Response =>
new Response(JSON.stringify(payload), {
status,
headers: buildResponseHeaders(request, {
"Content-Type": "application/json; charset=utf-8",
...init
})
});
export const emptyResponse = (request: Request, status = 204, init?: HeadersInit): Response =>
new Response(null, {
status,
headers: buildResponseHeaders(request, init)
});
export const fileResponse = (request: Request, body: Blob | Uint8Array, contentType: string, init?: HeadersInit): Response =>
new Response(body as BodyInit, {
status: 200,
headers: buildResponseHeaders(request, {
"Content-Type": contentType,
"Cache-Control": "private, max-age=300",
...init
})
});
export const parseJson = async <T>(request: Request, schema: { parse(data: unknown): T }): Promise<T> => {
const contentType = request.headers.get("content-type") ?? "";
if (!contentType.toLowerCase().includes("application/json")) {
throw new HttpError(415, "Expected application/json request body.");
}
let payload: unknown;
try {
payload = await request.json();
} catch {
throw new HttpError(400, "Malformed JSON request body.");
}
try {
return schema.parse(payload);
} catch (error) {
throw new HttpError(400, "Request validation failed.", { details: error });
}
};
export const errorResponse = (request: Request, error: unknown): Response => {
if (isHttpError(error)) {
const retryAfterMs =
typeof error.details === "object" &&
error.details !== null &&
"retryAfterMs" in error.details &&
typeof (error.details as { retryAfterMs?: unknown }).retryAfterMs === "number"
? Math.ceil(((error.details as { retryAfterMs: number }).retryAfterMs ?? 0) / 1000)
: undefined;
return jsonResponse(
request,
error.status,
{
error: error.expose ? error.message : "An internal server error occurred."
},
retryAfterMs ? { "Retry-After": String(retryAfterMs) } : undefined
);
}
if (config.nodeEnv !== "production") {
console.error(error);
}
return jsonResponse(request, 500, {
error: "An internal server error occurred."
});
};