Aller au contenu

Démarrage rapide — premier rendu en périphérie

Sur cette page, tu transformes une chaîne HTML en fichier PDF. Chaque appel présenté ici correspond à une méthode, dont le comportement est vérifié dans tests/Unit/Cloudflare/CloudflareHtmlRendererTest.php.

  • Un point de terminaison Worker qui expose le contrat de rendu via HTTPS.
  • Un jeton bearer que le Worker accepte.
  • Un client PSR-18 et des fabriques PSR-17 disponibles dans le chemin de chargement (voir /integrations/cloudflare/install/).

Le contrat du Worker, observé depuis CloudflareResponseParser : en cas de succès, il renvoie une réponse HTTP 200. La réponse a soit Content-Type: application/pdf (octets PDF bruts), soit Content-Type: application/json avec un champ pdf en base64. Tout statut autre que 200, ou tout corps qui ne commence pas par le marqueur %PDF, est traité comme un échec.

<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Cloudflare\CloudflareRendererConfig;
$config = new CloudflareRendererConfig(
workerUrl: 'https://pdf-renderer.example.workers.dev/render',
apiToken: getenv('CF_PDF_TOKEN') ?: throw new RuntimeException('CF_PDF_TOKEN not set'),
);

Le jeton est lu depuis l’environnement, jamais codé en dur. workerUrl doit être en HTTPS. Si tu fournis une URL http://, le pont la rejette avec Worker URL must use HTTPS avant qu’aucune requête ne soit envoyée.

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use NextPDF\Cloudflare\CloudflareHtmlRenderer;
$httpFactory = new HttpFactory();
$renderer = new CloudflareHtmlRenderer(
config: $config,
httpClient: new Client(), // PSR-18 ClientInterface
requestFactory: $httpFactory, // PSR-17 RequestFactoryInterface
streamFactory: $httpFactory, // PSR-17 StreamFactoryInterface
logger: null, // optional PSR-3 LoggerInterface
responseFactory: $httpFactory, // PSR-17; enables the pinned transport
);

Le constructeur requiert quatre arguments : la configuration, le client PSR-18, la fabrique de requêtes et la fabrique de flux. Quatre autres arguments sont optionnels : le journaliseur, la fabrique du moteur de rendu local, une politique de sécurité HTML explicite et la fabrique de réponses. Fournir la fabrique de réponses active le transport cURL épinglé si un ensemble d’IP résolues ou d’empreintes SPKI est présent (voir /integrations/cloudflare/security-and-operations/).

use NextPDF\Cloudflare\Exception\CloudflareNotAvailableException;
use NextPDF\Cloudflare\Exception\CloudflareRenderException;
try {
$result = $renderer->render('<h1>Hello from the edge</h1>');
if (!$result->isValid()) {
throw new RuntimeException('Worker did not return a valid PDF');
}
file_put_contents('output.pdf', $result->pdfData);
printf("Wrote %d bytes from edge %s in %.1f ms\n",
$result->size(),
$result->renderLocation !== '' ? $result->renderLocation : 'unknown',
$result->renderTimeMs,
);
} catch (CloudflareRenderException $e) {
// Worker answered but the render failed (HTTP error or malformed body).
fwrite(STDERR, 'Render failed: ' . $e->getMessage() . PHP_EOL);
exit(1);
} catch (CloudflareNotAvailableException $e) {
// Worker unreachable and no usable fallback.
fwrite(STDERR, 'Edge unavailable: ' . $e->getMessage() . PHP_EOL);
exit(2);
}

render() utilise par défaut la largeur A4 (595.28 points PDF) et une hauteur détectée automatiquement (heightPt: 0). Les deux types d’exception sont volontairement distincts. Une CloudflareRenderException correspond à un échec côté Worker, et l’appel n’est pas réessayé avec un repli. CloudflareNotAvailableException signifie que la périphérie n’a pas pu être atteinte et qu’aucun repli local n’était disponible.

CloudflareRenderResult est final readonly. Les champs ci-dessous sont renseignés à partir des en-têtes de réponse sur le chemin binaire, ou à partir des champs JSON sur le chemin JSON.

MembreSource
pdfDataOctets PDF bruts
widthPtLa largeur demandée
heightPtEn-tête X-Pdf-Height-Pt / JSON heightPt ; vaut par défaut 841.89 (hauteur A4) lorsqu’il est absent ou non positif
contentHeightPxX-Content-Height-Px / JSON contentHeightPx
renderLocationDérivé du suffixe de l’en-tête CF-Ray (chemin binaire) ou du JSON renderLocation
renderTimeMsX-Render-Time-Ms / JSON renderTimeMs
size()strlen($pdfData)
isValid()true lorsque les octets commencent par %PDF

Optionnel — format de papier, polices et CSS personnalisés

Section intitulée « Optionnel — format de papier, polices et CSS personnalisés »
$result = $renderer->render(
html: '<div style="font-family: NotoSansCJK;">繁體中文文件</div>',
widthPt: 595.28,
heightPt: 841.89, // explicit A4; 0 lets the Worker auto-detect
fontFiles: ['NotoSansCJKtc-Regular.ttf'],
);

fontFiles n’est utile que lorsque la configuration définit r2FontBucket. La charge utile transporte alors le nom du bucket et les chemins des fichiers de police demandés, afin que le Worker puisse les charger.

if ($renderer->isAvailable()) {
$result = $renderer->render($html);
}

isAvailable() envoie une requête HTTP HEAD authentifiée à l’URL du Worker. Elle renvoie true lorsque le statut est inférieur à 500. Elle renvoie false sans lever d’exception lorsque la configuration est invalide ou que la requête échoue. Considère-la comme une indication, pas comme une garantie. Le Worker peut tout de même échouer sur le POST qui suit.

  • /integrations/cloudflare/production-usage/ — mise en place du repli, télémétrie, archivage R2.
  • /integrations/cloudflare/troubleshooting/ — correspondance de chaque échec avec son exception et son message.
  • /integrations/cloudflare/configuration/ — la référence complète des champs.