Add URL→PDF endpoint, usage tracking middleware, free tier limits

This commit is contained in:
DocFast Bot 2026-02-14 13:02:40 +00:00
parent 8e03b8ab3c
commit 6896b72e0c
5 changed files with 158 additions and 4 deletions

View file

@ -1,5 +1,5 @@
import { Router, Request, Response } from "express";
import { renderPdf } from "../services/browser.js";
import { renderPdf, renderUrlPdf } from "../services/browser.js";
import { markdownToHtml, wrapHtml } from "../services/markdown.js";
export const convertRouter = Router();
@ -76,3 +76,43 @@ convertRouter.post("/markdown", async (req: Request, res: Response) => {
res.status(500).json({ error: "PDF generation failed", detail: err.message });
}
});
// POST /v1/convert/url
convertRouter.post("/url", async (req: Request, res: Response) => {
try {
const body = req.body as { url?: string; format?: string; landscape?: boolean; margin?: any; printBackground?: boolean; waitUntil?: string; filename?: string };
if (!body.url) {
res.status(400).json({ error: "Missing 'url' field" });
return;
}
// Basic URL validation
try {
const parsed = new URL(body.url);
if (!["http:", "https:"].includes(parsed.protocol)) {
res.status(400).json({ error: "Only http/https URLs are supported" });
return;
}
} catch {
res.status(400).json({ error: "Invalid URL" });
return;
}
const pdf = await renderUrlPdf(body.url, {
format: body.format,
landscape: body.landscape,
margin: body.margin,
printBackground: body.printBackground,
waitUntil: body.waitUntil,
});
const filename = body.filename || "page.pdf";
res.setHeader("Content-Type", "application/pdf");
res.setHeader("Content-Disposition", `inline; filename="${filename}"`);
res.send(pdf);
} catch (err: any) {
console.error("Convert URL error:", err);
res.status(500).json({ error: "PDF generation failed", detail: err.message });
}
});