Files
training-software/certificates/render_client.py
Paperclip CTO 94bba1ec5d
All checks were successful
CI Build / Build Container (push) Successful in 5s
CI Quality / Ruff Lint (push) Successful in 6s
CI Security / Bandit + pip-audit (push) Successful in 21s
CI Tests / Django Tests (push) Successful in 35s
CI Tests / OpenAPI Schema (push) Successful in 16s
TRA-408 isolate certificate rendering in internal service
2026-05-19 14:23:20 +02:00

52 lines
1.9 KiB
Python

from __future__ import annotations
import json
import os
from urllib import error, request
from django.conf import settings
from .renderer import RenderError, validate_certificate_context
MAX_PDF_BYTES = 5 * 1024 * 1024
def render_certificate_via_service(context: dict, output_path: str) -> str:
"""Validate and send render request to internal renderer service."""
validated = validate_certificate_context(context)
service_url = getattr(settings, "CERTIFICATE_RENDERER_URL", "http://certificate-renderer:8090/render")
timeout = int(getattr(settings, "CERTIFICATE_RENDERER_TIMEOUT_SECONDS", 20))
token = getattr(settings, "CERTIFICATE_RENDERER_TOKEN", "")
payload = json.dumps({"context": validated}).encode("utf-8")
req = request.Request(service_url, data=payload, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("Accept", "application/pdf")
if token:
req.add_header("X-Renderer-Token", token)
try:
with request.urlopen(req, timeout=timeout) as response:
if response.status != 200:
raise RenderError(f"renderer returned HTTP {response.status}")
content_type = response.headers.get("Content-Type", "")
if "application/pdf" not in content_type:
raise RenderError(f"renderer returned invalid content-type: {content_type}")
pdf_bytes = response.read(MAX_PDF_BYTES + 1)
except error.HTTPError as exc:
detail = exc.read(1024).decode("utf-8", errors="replace")
raise RenderError(f"renderer HTTPError {exc.code}: {detail}")
except error.URLError as exc:
raise RenderError(f"renderer not reachable: {exc.reason}")
if len(pdf_bytes) > MAX_PDF_BYTES:
raise RenderError("renderer returned oversized PDF")
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, "wb") as f:
f.write(pdf_bytes)
return output_path