Référence de l'API Cloudflare
Le package NextPDF\Cloudflare sert de pont de rendu en périphérie : ton processus PHP garde le HTML, tandis qu’un Worker Cloudflare héberge le navigateur headless. Le package expose un renderer HTML adossé au Worker (CloudflareHtmlRenderer) et les value objects qu’il renvoie, une couche de protection des requêtes destinée aux endpoints de rendu (ApiProtection), un service d’archivage R2 pour stocker les PDF rendus (R2ArchiveManager), ainsi que des helpers de transport épinglé pour le durcissement TLS/DNS. La configuration est portée par trois objets immuables (CloudflareRendererConfig, ApiProtectionConfig, R2ArchiveConfig).
Pour commencer : si tu découvres le package, construis un CloudflareRendererConfig, branche-le dans CloudflareHtmlRenderer, puis appelle render(). Ce seul appel envoie ton HTML au Worker et te renvoie un CloudflareRenderResult contenant les octets du PDF. Tout le reste (protection, archivage, épinglage) s’articule autour de ce même appel.
Tâches courantes
Section intitulée « Tâches courantes »Les extraits ci-dessous couvrent les workflows réels les plus fréquents de ce package. Chacun est autonome, vérifié dans le code source de src/Cloudflare/, et lit les secrets depuis l’environnement.
Rendre une chaîne HTML en PDF en périphérie — l’appel de rendu canonique unique :
<?php
declare(strict_types=1);
use GuzzleHttp\Client;use GuzzleHttp\Psr7\HttpFactory;use NextPDF\Cloudflare\CloudflareHtmlRenderer;use NextPDF\Cloudflare\CloudflareRendererConfig;
$httpFactory = new HttpFactory();
$renderer = new CloudflareHtmlRenderer( config: new CloudflareRendererConfig( workerUrl: 'https://pdf-renderer.example.workers.dev/render', apiToken: getenv('CF_PDF_TOKEN') ?: throw new RuntimeException('CF_PDF_TOKEN not set'), ), httpClient: new Client(), requestFactory: $httpFactory, streamFactory: $httpFactory, responseFactory: $httpFactory,);
$result = $renderer->render('<h1>Hello from the edge</h1>', widthPt: 595.28);
if ($result->isValid()) { file_put_contents('output.pdf', $result->pdfData);}Ce qu’il fait : il transmet le HTML au Worker via HTTPS et écrit sur le disque les octets du PDF A4 renvoyé, une fois que isValid() a confirmé qu’il s’agit bien d’un PDF.
Archiver un PDF rendu dans R2 et renvoyer un lien à courte durée de vie :
<?php
declare(strict_types=1);
use NextPDF\Cloudflare\R2ArchiveConfig;use NextPDF\Cloudflare\R2ArchiveManager;
$archive = new R2ArchiveManager( config: R2ArchiveConfig::fromArray([ 'bucket_name' => 'pdf-archive', 'account_id' => getenv('CF_ACCOUNT_ID') ?: '', 'access_key_id' => getenv('R2_ACCESS_KEY_ID') ?: '', 'secret_access_key' => getenv('R2_SECRET_ACCESS_KEY') ?: '', ]), httpClient: $httpClient, // PSR-18 ClientInterface requestFactory: $requestFactory, // PSR-17 RequestFactoryInterface streamFactory: $streamFactory, // PSR-17 StreamFactoryInterface);
$upload = $archive->upload($result->pdfData, 'invoice-1234.pdf');
$signedUrl = $upload->isValid() ? $archive->generateSignedUrl($upload->key, expiresInSeconds: 600) : null;Ce qu’il fait : il téléverse les octets du PDF vers une clé R2 partitionnée par date et, en cas de succès, génère une URL pré-signée de 10 minutes pour un téléchargement temporaire.
Protéger un endpoint de rendu avant de déclencher un travail Worker coûteux :
<?php
declare(strict_types=1);
use NextPDF\Cloudflare\ApiKeyValidator;use NextPDF\Cloudflare\ApiProtection;use NextPDF\Cloudflare\ApiProtectionConfig;
$protection = new ApiProtection( config: new ApiProtectionConfig(maxRequestsPerMinute: 30), keyValidator: new ApiKeyValidator([getenv('RENDER_API_KEY') ?: '']),);
$decision = $protection->checkRequest( clientId: $clientIp, payloadSize: strlen($html), apiKey: $presentedApiKey,);
if (!$decision->allowed) { // Reject with 429 and rate-limit headers before any render call. return [429, $decision->toHeaders(), $decision->denialReason];}Ce qu’il fait : il valide la clé d’API, contrôle la taille de la charge utile, puis la limite de débit par client, et renvoie une décision unique avec les en-têtes de réponse à attacher quand la requête est refusée.
Renderer
Section intitulée « Renderer »Le tableau du renderer constitue la surface d’API centrale. Utilise-le quand tu construis la configuration, que tu bâtis le renderer ou que tu effectues les appels de rendu et de disponibilité.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
new CloudflareRendererConfig(string $workerUrl, string $apiToken, int $renderTimeout = 30, string $defaultCss = '', int $maxHtmlSize = 5000000, ?string $r2FontBucket = null, bool $fallbackToLocal = true, array $pinnedPublicKeys = [], array $backupPublicKeys = []) | URL du Worker, jeton bearer, délai d’expiration, CSS, limite de taille, bucket de polices R2 optionnel, drapeau de repli, ensembles d’épingles. | Le repli local est activé ; l’épinglage est désactivé quand les tableaux d’épingles sont vides. | CloudflareRendererConfig | aucune attendue. | Garde le jeton d’API secret ; préfère les URL de Worker en HTTPS. |
CloudflareRendererConfig::fromArray(array $config) | worker_url, api_token, render_timeout, default_css, max_html_size, r2_font_bucket, fallback_to_local, tableaux d’épingles. | Les clés optionnelles manquantes utilisent les valeurs par défaut du constructeur. | CloudflareRendererConfig | aucune attendue. | Correspond aux tableaux de configuration de style framework. |
CloudflareRendererConfig::isValid() | aucun. | Exige une URL de Worker et un jeton d’API non vides. | bool | aucune attendue. | Une configuration invalide déclenche un repli ou un échec dans le renderer. |
CloudflareRendererConfig::allPublicKeyPins() | aucun. | Combine les épingles de clé publique primaires et de secours. | list<string> | aucune attendue. | Une liste vide désactive l’épinglage. |
new CloudflareHtmlRenderer(CloudflareRendererConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, ?LoggerInterface $logger = null, ?LocalRendererFactoryInterface $localRendererFactory = null, ?HtmlSecurityPolicyInterface $htmlSecurityPolicy = null, ?ResponseFactoryInterface $responseFactory = null) | Configuration, dépendances HTTP PSR, logger optionnel, factory de repli local optionnelle, politique HTML optionnelle, factory de réponse optionnelle. | Utilise DefaultHtmlSecurityPolicy quand aucune politique HTML n’est fournie. | CloudflareHtmlRenderer | Erreurs de câblage du conteneur. | La factory de réponse active le transport cURL épinglé lorsque c’est nécessaire. |
CloudflareHtmlRenderer::render(string $html, float $widthPt = 595.28, float $heightPt = 0, array $fontFiles = []) | HTML, largeur de page, hauteur de page, fichiers de polices dans R2. | Largeur A4 ; hauteur automatique ; aucun fichier de police. | CloudflareRenderResult | CloudflareNotAvailableException, CloudflareRenderException, échecs de validation. | Valide la taille du HTML et l’URL du Worker avant toute E/S réseau. |
CloudflareHtmlRenderer::getHtmlSecurityPolicy() | aucun. | Renvoie la politique de la couche de parsing configurée. | HtmlSecurityPolicyInterface | aucune attendue. | À utiliser avec la protection des endpoints et la validation de l’URL du Worker. |
CloudflareHtmlRenderer::isAvailable() | aucun. | Requête HEAD vers le Worker quand la configuration est valide. | bool | Renvoie false en cas d’erreur. | À utiliser pour les vérifications de disponibilité, pas comme unique garde-fou à l’exécution. |
Value objects du renderer et sécurité
Section intitulée « Value objects du renderer et sécurité »Utilise ce tableau quand tu as besoin des value objects de request/result (CloudflareRenderResult, CloudflareRenderPayload) ou des vérifications statiques de la couche de transport qui valident le HTML, l’URL du Worker et les épingles DNS avant toute E/S réseau.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
new CloudflareRenderResult(string $pdfData, float $widthPt, float $heightPt, float $contentHeightPx = 0.0, string $renderLocation = '', float $renderTimeMs = 0.0) | Octets du PDF, largeur, hauteur, hauteur de contenu mesurée, emplacement en périphérie, durée de rendu. | Métadonnées vides quand le Worker ne les rapporte pas. | CloudflareRenderResult | aucune attendue. | Généralement renvoyé par CloudflareResponseParser::parse(). |
CloudflareRenderResult::isValid() | aucun. | Vérifie la présence d’octets PDF non vides commençant par un en-tête PDF. | bool | aucune attendue. | À utiliser avant l’archivage ou la transmission des octets à une autre couche. |
CloudflareRenderResult::size() | aucun. | Compte les octets du PDF rendu. | int | aucune attendue. | Alimente la logique de quota et d’audit avec cette valeur. |
new CloudflareRenderPayload(string $html, float $widthPt, float $heightPt = 0, string $defaultCss = '', ?string $r2FontBucket = null, array $fontFiles = []) | HTML, dimensions, CSS, bucket de polices R2 optionnel, liste de fichiers de polices. | Hauteur automatique, pas de CSS par défaut, pas de bucket de polices R2, pas de fichiers de polices. | CloudflareRenderPayload | aucune attendue. | Value object de la charge utile de requête. |
CloudflareRenderPayload::toJson() | aucun. | Sérialise le HTML, la taille, le CSS et les références de polices pour le Worker. | string | Erreurs d’encodage JSON. | API bas niveau de la charge utile de requête. |
CloudflareResponseParser::parse(ResponseInterface $response, float $requestedWidthPt) | Réponse du Worker et largeur demandée. | Accepte les réponses PDF binaires et les réponses JSON structurées. | CloudflareRenderResult | CloudflareRenderException en cas de sortie du Worker en échec ou invalide. | Parser central utilisé par le renderer. |
CloudflareSecurityPolicy::validate(string $html, int $maxSize) | Entrée HTML et limite de taille. | Applique la politique d’entrée HTML du package. | void | Exception de validation. | Maintient les contrôles d’entrée non fiable en dehors de la frontière du Worker. |
CloudflareSecurityPolicy::validateWorkerUrl(string $url) | URL du Worker. | Analyse et valide la destination. | array | Exception de validation. | Bloque les formes d’endpoint non sûres avant toute E/S réseau. |
CloudflareSecurityPolicy::assertPinsStillValid(string $host, array $pinnedIps) | Hôte et liste d’IP épinglées. | Vérifie les attentes d’épingles DNS. | void | Exception de validation quand les épingles sont périmées ou invalides. | À utiliser lors des vérifications opérationnelles pour les déploiements épinglés. |
Protection de l’API
Section intitulée « Protection de l’API »Utilise ce tableau quand tu protèges un endpoint de rendu : validation de la clé d’API, contrôles de la taille de la charge utile et de la limite de débit, et les objets result/header qu’ils produisent.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
new ApiProtection(ApiProtectionConfig $config, ?ApiKeyValidator $keyValidator = null, ?Closure $clock = null) | Configuration de protection, validateur de clé optionnel, horloge optionnelle. | Utilise l’heure système quand aucune horloge n’est fournie. | ApiProtection | aucune attendue. | Injecte une horloge déterministe dans les tests. |
ApiProtection::checkRequest(string $clientId, int $payloadSize, string $apiKey = '') | Identifiant du client, taille de la charge utile, clé d’API optionnelle. | Une clé d’API vide n’est autorisée que lorsque la configuration n’exige pas de clés. | ApiProtectionResult | aucune attendue. | Vérifie la clé d’API, la taille, puis les limites de débit. |
ApiProtection::getRateLimit(string $clientId) | Identifiant du client. | N’enregistre pas de requête. | RateLimitResult | aucune attendue. | À utiliser pour ajouter des en-têtes de limite de débit. |
new ApiKeyValidator(array $validKeys = []) | Liste de clés valides en clair. | Une liste vide rejette toutes les clés. | ApiKeyValidator | aucune attendue. | Stocke les secrets en dehors du code et hydrate-les via la configuration. |
ApiKeyValidator::validate(string $key) | Clé brute. | Comparaison à temps constant avec les clés en clair configurées. | bool | aucune attendue. | Paramètre sensible ; ne journalise pas les clés brutes. |
ApiKeyValidator::addKey(string $key) | Clé brute. | Ajoute une clé hachée à une nouvelle instance de validateur. | self | aucune attendue. | Traite l’instance renvoyée comme le validateur mis à jour. |
ApiKeyValidator::revokeKey(string $key) | Clé brute. | Supprime le hachage correspondant d’une nouvelle instance de validateur. | self | aucune attendue. | Traite l’instance renvoyée comme le validateur mis à jour. |
ApiKeyValidator::hashKey(string $key) | Clé brute. | Produit la représentation de hachage stockée. | string | aucune attendue. | N’expose pas les hachages dans les journaux ni dans les réponses client. |
ApiKeyValidator::validateHashed(string $key, array $hashedKeys) | Clé brute et hachages candidats. | Comparaison à temps constant avec les hachages fournis. | bool | aucune attendue. | Helper bas niveau pour les stores de clés personnalisés. |
new ApiProtectionConfig(int $maxRequestsPerMinute = 60, int $maxRequestsPerHour = 1000, int $maxPayloadSizeBytes = 10485760, array $allowedOrigins = [], bool $requireApiKey = true, string $apiKeyHeader = 'X-Api-Key', int $rateLimitWindowSeconds = 60) | Limites de requêtes, limite de charge utile, origines autorisées, exigence de clé d’API, nom d’en-tête, durée de la fenêtre. | 60/minute, 1000/hour, charge utile de 10 Mio, clé d’API requise. | ApiProtectionConfig | aucune attendue. | Construis-le directement dans les tests ou hydrate-le avec fromArray(). |
ApiProtectionConfig::fromArray(array $data) | max_requests_per_minute, max_requests_per_hour, max_payload_size_bytes, allowed_origins, require_api_key, api_key_header, rate_limit_window_seconds. | Les clés manquantes utilisent les valeurs par défaut du constructeur. | ApiProtectionConfig | aucune attendue. | À utiliser pour l’hydratation de la configuration d’un framework. |
ApiProtectionConfig::isValid() | aucun. | Exige des limites positives et des valeurs size/window cohérentes. | bool | aucune attendue. | Valide la configuration avant d’exposer un endpoint. |
new ApiProtectionResult(bool $allowed, string $denialReason = '', ?RateLimitResult $rateLimit = null) | Décision, motif de refus, résultat de limite de débit optionnel. | Motif de refus vide et aucun résultat de limite de débit. | ApiProtectionResult | aucune attendue. | Renvoyé par ApiProtection::checkRequest(). |
ApiProtectionResult::toHeaders() | aucun. | Émet les en-têtes de limite de débit quand des données de débit existent. | array<string, string> | aucune attendue. | À attacher aux réponses du Worker ou du framework. |
new RateLimitResult(bool $allowed, int $remainingRequests, int $retryAfterSeconds, string $clientId) | Décision, nombre restant, délai de réessai, ID du client. | Aucune valeur par défaut. | RateLimitResult | aucune attendue. | Résultat immuable pour une seule vérification. |
RateLimitResult::toHeaders() | aucun. | Émet les en-têtes de limite restante et de réinitialisation. | array<string, string> | aucune attendue. | À utiliser pour l’observabilité et le backoff client. |
new RateLimitEntry(string $clientId, int $requestCount = 0, int $windowStart = 0, int $hourlyCount = 0, int $hourlyWindowStart = 0) | ID du client et compteurs mutables. | Les compteurs démarrent à zéro. | RateLimitEntry | aucune attendue. | Objet de suivi en mémoire. |
RateLimitEntry::increment() | aucun. | Incrémente le compteur en mémoire pour un seul client/window. | void | aucune attendue. | Helper bas niveau utilisé par ApiProtection. |
RateLimitEntry::isExpired(int $windowSeconds) | Durée de la fenêtre en secondes. | Compare avec l’heure actuelle. | bool | aucune attendue. | Helper d’expiration à l’exécution. |
RateLimitEntry::isExpiredAt(int $now, int $windowSeconds) | Valeur d’horloge et durée de la fenêtre. | Compare avec la valeur d’horloge fournie. | bool | aucune attendue. | Helper de test déterministe. |
RateLimitEntry::reset() | aucun. | Réinitialise le compteur et l’heure de début de la fenêtre. | void | aucune attendue. | Utilisé quand une nouvelle fenêtre commence. |
Archive R2
Section intitulée « Archive R2 »Utilise ce tableau quand tu stockes des PDF rendus dans Cloudflare R2 : le service d’archivage, ses types de configuration et de clé d’objet, et le résultat de téléversement que tu inspectes avant d’exposer une URL.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
new R2ArchiveManager(R2ArchiveConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory) | Configuration R2 et factories/client HTTP PSR. | Aucun appel réseau pendant la construction. | R2ArchiveManager | Erreurs de câblage du conteneur. | Service d’archivage principal. |
R2ArchiveManager::upload(string $pdfData, string $filename, array $metadata = []) | Octets PDF bruts, nom de fichier d’origine, métadonnées de type chaîne. | Métadonnées vides ; clé partitionnée par date. | R2UploadResult | Renvoie un résultat d’échec en cas d’échec de configuration, de taille, HTTP ou de transport. | Ne lève pas d’exception pour un échec de téléversement normal. |
R2ArchiveManager::generateSignedUrl(string $key, int $expiresInSeconds = 3600) | Clé d’objet et TTL de l’URL. | URL signée d’une heure. | string | Erreurs de signature dues à une configuration invalide. | Conserve des TTL courts pour les PDF sensibles. |
R2ArchiveManager::buildObjectKey(string $filename) | Nom de fichier d’origine. | Utilise le préfixe de chemin configuré et la date actuelle. | R2ObjectKey | aucune attendue. | À utiliser pour un partitionnement d’archive prévisible. |
R2ArchiveManager::createPutRequest(R2ObjectKey $key, string $data, array $metadata = []) | Clé d’objet, octets bruts, métadonnées. | Signe une requête PUT. | RequestInterface | Erreurs de construction de requête. | API bas niveau pour les transports personnalisés. |
new R2ArchiveConfig(string $bucketName, string $accountId, string $accessKeyId, string $secretAccessKey, string $endpoint = '', string $pathPrefix = 'pdfs/', int $maxFileSizeBytes = 104857600) | Bucket, ID de compte, identifiants, surcharge d’endpoint, préfixe de clé, taille d’objet maximale. | Endpoint dérivé, préfixe pdfs/, taille d’objet maximale de 100 Mio. | R2ArchiveConfig | InvalidArgumentException pour les noms de bucket invalides. | Traite les identifiants comme une configuration contenant des secrets. |
R2ArchiveConfig::fromArray(array $data) | ID de compte, bucket, identifiants, préfixe de chemin, surcharge d’endpoint, taille maximale. | Les valeurs manquantes utilisent les valeurs par défaut du constructeur. | R2ArchiveConfig | Nom de bucket invalide s’il est fourni. | À utiliser pour l’hydratation de la configuration de l’application. |
R2ArchiveConfig::isValid() | aucun. | Exige un compte, un bucket, une clé d’accès et une clé secrète non vides. | bool | aucune attendue. | Une configuration invalide fait échouer les téléversements avec des résultats structurés. |
R2ArchiveConfig::getEndpoint() | aucun. | Utilise l’endpoint explicite ou dérive l’endpoint Cloudflare R2 à partir de l’ID de compte. | string | aucune attendue. | Utilisé pour la construction des requêtes signées. |
new R2ObjectKey(string $key, string $bucket) | Clé d’objet complète et bucket. | Aucune normalisation. | R2ObjectKey | aucune attendue. | Généralement créé par R2ObjectKey::generate(). |
R2ObjectKey::generate(string $prefix, string $filename, ?DateTimeInterface $date = null) | Préfixe, nom de fichier d’origine, date optionnelle. | Clé d’objet partitionnée par date et assainie. | R2ObjectKey | aucune attendue. | Injecte la date dans les tests pour des clés déterministes. |
R2ObjectKey::fullPath() | aucun. | Assemble le chemin de partition et le nom de fichier de l’objet. | string | aucune attendue. | Stocke cette valeur comme clé d’objet. |
new R2UploadResult(bool $success, string $key, string $etag = '', int $size = 0, string $error = '') | Indicateur de succès, clé d’objet, ETag, taille en octets, message d’erreur. | ETag vide, taille nulle, erreur vide. | R2UploadResult | aucune attendue. | Renvoyé par R2ArchiveManager::upload(). |
R2UploadResult::isValid() | aucun. | Valide quand le téléversement a réussi et que la clé et l’ETag sont tous deux présents. | bool | aucune attendue. | Vérifie avant d’exposer des URL. |
R2UploadResult::publicUrl(string $customDomain = '') | Domaine public personnalisé optionnel. | Renvoie la clé d’objet brute quand aucun domaine personnalisé n’est fourni. | string | aucune attendue. | Évite les URL publiques pour les documents sensibles, sauf si la politique l’autorise. |
Helpers de transport
Section intitulée « Helpers de transport »Utilise ce tableau uniquement pour le câblage bas niveau : l’épinglage IP/SPKI au niveau cURL et les contrats du renderer local utilisés comme chemin de repli quand le Worker est injoignable.
| Symbole | Paramètres | Comportement par défaut | Renvoie | Lève ou échoue avec | Notes |
|---|---|---|---|---|---|
new PinnedCurlTransport(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, array $pinnedIps = [], array $pinnedPublicKeys = [], int $timeoutSeconds = 30) | Factories PSR-17, IP épinglées, clés publiques épinglées, délai d’expiration. | Aucune épingle et délai d’expiration de 30 secondes. | PinnedCurlTransport | aucune attendue. | À utiliser uniquement quand l’épinglage au niveau cURL est requis. |
PinnedCurlTransport::sendRequest(RequestInterface $request) | Requête PSR-7. | Envoie la requête via cURL avec le délai d’expiration et les contrôles d’épinglage configurés. | ResponseInterface | Exceptions de transport PSR-18. | À utiliser uniquement quand les clients HTTP du framework ne peuvent pas appliquer la même politique d’épinglage. |
PinnedCurlTransport::buildCurlOptions(RequestInterface $request, string $host, int $port) | Requête, hôte cible, port cible. | Construit le tableau d’options cURL utilisé par sendRequest(). | array | Erreurs de requête ou de configuration d’épingles invalides. | Point d’accroche bas niveau pour les tests et le diagnostic. |
LocalRendererInterface::render(string $html, array $options = []) | HTML et options du renderer. | Contrat uniquement ; l’implémentation décide des valeurs par défaut. | string | Erreurs de rendu propres à l’implémentation. | Utilisé comme repli local quand le rendu par le Worker est indisponible. |
LocalRendererFactoryInterface::create() | aucun. | Crée une implémentation de renderer local. | LocalRendererInterface | Erreurs de factory ou de dépendance. | Maintient la construction du renderer de repli en dehors de CloudflareHtmlRenderer. |
Notes de développement
Section intitulée « Notes de développement »- Considère l’URL du Worker comme une frontière réseau. Valide la destination, la taille et l’authentification avant le rendu.
- Utilise les résultats de protection de l’API comme des décisions de politique, pas comme un flux de contrôle par exceptions.
- Les téléversements R2 renvoient des résultats de succès ou d’erreur structurés ; traite les deux cas.