feat: add unhandled error handlers + SSRF and Content-Disposition tests
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m5s

This commit is contained in:
DocFast Dev 2026-02-25 13:10:32 +00:00
parent 288d6c7aab
commit c4fea7932c
2 changed files with 32 additions and 0 deletions

View file

@ -197,6 +197,28 @@ describe("URL to PDF", () => {
expect(data.error).toContain("private");
});
it("blocks 0.0.0.0 (SSRF protection)", async () => {
const res = await fetch(`${BASE}/v1/convert/url`, {
method: "POST",
headers: { Authorization: "Bearer test-key", "Content-Type": "application/json" },
body: JSON.stringify({ url: "http://0.0.0.0" }),
});
expect(res.status).toBe(400);
const data = await res.json();
expect(data.error).toContain("private");
});
it("returns default filename in Content-Disposition for /convert/html", async () => {
const res = await fetch(`${BASE}/v1/convert/html`, {
method: "POST",
headers: { Authorization: "Bearer test-key", "Content-Type": "application/json" },
body: JSON.stringify({ html: "<p>hello</p>" }),
});
expect(res.status).toBe(200);
const disposition = res.headers.get("content-disposition");
expect(disposition).toContain('filename="document.pdf"');
});
it("rejects invalid protocol (ftp)", async () => {
const res = await fetch(`${BASE}/v1/convert/url`, {
method: "POST",

View file

@ -422,6 +422,16 @@ async function start() {
};
process.on("SIGTERM", () => shutdown("SIGTERM"));
process.on("SIGINT", () => shutdown("SIGINT"));
process.on("uncaughtException", (err) => {
logger.fatal({ err }, "Uncaught exception — shutting down");
process.exit(1);
});
process.on("unhandledRejection", (reason) => {
logger.fatal({ err: reason }, "Unhandled rejection — shutting down");
process.exit(1);
});
}
if (process.env.NODE_ENV !== "test") {