Renderização de PDF
capabilities.pdf.render transforma HTML em PDF sem conhecer endpoint, credencial ou implementação — com limites, cancelamento e erros com retryable.
1. Declare a dependência
Em oon.deploy.json (não em central.app.json):
{
"capabilities": {
"pdfRendering": { "required": true, "minVersion": "1.0.0" }
}
}
Não adicione URL, usuário, senha ou implementation reference — o runtime resolve na publicação.
2. Crie a rota
const { capabilities, defineRoutes, GenericError } = require("@oondemand/oon-core-back");
defineRoutes("/pdf", (router) => {
router.private.post("/render", { permission: "pdf.render" }, async (req, res) => {
if (typeof req.body?.html !== "string" || !req.body.html.trim()) {
throw new GenericError("Informe o HTML.", { statusCode: 422, code: "PDF_HTML_REQUIRED" });
}
const controller = new AbortController();
const abort = () => controller.abort();
req.once("aborted", abort);
res.once("close", abort);
try {
const pdf = await capabilities.pdf.render(
{ html: req.body.html, format: req.body.format || "A4", printBackground: true },
{
...req.accessContext,
correlationId: req.correlationId,
environment: process.env.APP_ENVIRONMENT,
signal: controller.signal,
},
);
res.type("application/pdf");
res.set("Content-Disposition", 'attachment; filename="documento.pdf"');
res.send(pdf);
} finally {
req.off("aborted", abort);
res.off("close", abort);
}
});
});
Declare pdf.render em rbac.permissions e conceda só aos perfis necessários.
Assinatura
capabilities.pdf.render(input, context): Promise<Buffer>
input |
Tipo | Regra / padrão |
|---|---|---|
html |
string | obrigatório; máximo padrão de 2 MiB |
format |
A3 | A4 | A5 | Letter | Legal |
A4 |
landscape |
boolean | false |
marginTop/Bottom/Left/Right |
number | polegadas, 0 a 4; 0.39 |
printBackground |
boolean | true |
timeoutMs |
number | mín. 1.000; padrão 30.000; máx. do runtime 60.000 |
context aceita tenantId, appCode, environment, operationId, correlationId/requestId, signal e, só em testes, fetchImpl. A saída começa com %PDF- e tem limite padrão de 20 MiB. O alias capabilities.pdfRendering.render é compatível.
3. Preview e download no frontend
<iframe title="Prévia" sandbox="" srcDoc={html} />
import { useOonApi } from "@oondemand/oon-core-front";
function DownloadPdfButton({ html }: { html: string }) {
const { http } = useOonApi();
async function download() {
const response = await http.post("/pdf/render", { html, format: "A4" }, { responseType: "blob" });
const url = URL.createObjectURL(response.data);
const link = document.createElement("a");
link.href = url;
link.download = "documento.pdf";
link.click();
URL.revokeObjectURL(url);
}
return <button onClick={download}>Gerar PDF</button>;
}
Nunca envie a geração diretamente a um endpoint de infraestrutura pelo navegador.
Erros
PdfRenderingError expõe code, statusCode, retryable e detalhes sanitizados.
| Código | Retry | Significado |
|---|---|---|
PDF_RENDERING_INVALID_INPUT |
não | HTML vazio ou acima do limite |
PDF_RENDERING_INVALID_OPTIONS |
não | formato, margem ou opção inválida |
PDF_RENDERING_UNAVAILABLE |
sim | capability não resolvida no ambiente |
PDF_RENDERING_CREDENTIAL_UNAVAILABLE |
sim | credencial interna não injetada |
PDF_RENDERING_IMPLEMENTATION_ERROR |
sim | implementação respondeu com falha |
PDF_RENDERING_TIMEOUT |
sim | prazo excedido ou sinal abortado |
PDF_RENDERING_SATURATED |
sim | concorrência/fila excedida |
PDF_RENDERING_TRANSPORT_ERROR |
sim | falha transitória de transporte |
PDF_RENDERING_INVALID_OUTPUT |
sim | saída inválida ou acima do limite |
Repita apenas quando error.retryable === true, com backoff e idempotência na operação chamadora.
Segurança
- trate HTML do usuário como não confiável; sanitize e use interpolação escapada;
- prefira HTML autocontido — recursos remotos tornam o resultado não determinístico;
- nunca inclua segredos no HTML;
- não registre HTML nem bytes do PDF; registre correlação, duração, tamanhos e código;
- propague cancelamento por
AbortSignal; - no runtime local, falha fechado com
PDF_RENDERING_UNAVAILABLE; - em testes, injete um transport fake por
capabilities.configurePdfRenderingque devolva bytes iniciados por%PDF-.