Salta ai contenuti

Avvio rapido — primo rendering all'edge

Questa pagina mostra come trasformare una stringa HTML in un file PDF. Ogni chiamata mostrata qui corrisponde a un metodo e il comportamento di ciascun metodo è verificato in tests/Unit/Cloudflare/CloudflareHtmlRendererTest.php.

  • Un endpoint Worker che espone il contratto di rendering via HTTPS.
  • Un bearer token accettato dal Worker.
  • Un client PSR-18 e le factory PSR-17 disponibili nel percorso di esecuzione (vedere /integrations/cloudflare/install/).

Secondo il contratto del Worker, così come interpretato da CloudflareResponseParser, una richiesta riuscita restituisce HTTP 200. La risposta contiene Content-Type: application/pdf (byte PDF grezzi) oppure Content-Type: application/json con un campo pdf codificato in base64. Qualsiasi stato diverso da 200 o un corpo che non inizi con il marcatore %PDF viene considerato un errore.

<?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'),
);

Il token viene letto dall’ambiente e non va mai inserito nel codice. workerUrl deve usare HTTPS. Se viene passato un URL http://, il bridge lo rifiuta con Worker URL must use HTTPS prima dell’invio di qualsiasi richiesta.

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
);

Il costruttore richiede quattro argomenti: la configurazione, il client PSR-18, la request factory e la stream factory. Altri quattro argomenti sono facoltativi: il logger, la factory del renderer locale, un criterio di sicurezza HTML esplicito e la response factory. Quando viene fornita la response factory, il trasporto cURL con pinning viene abilitato se è presente un insieme di IP risolti o un insieme di pin SPKI (vedere /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() usa per impostazione predefinita la larghezza A4 (595.28 punti PDF) e l’altezza rilevata automaticamente (heightPt: 0). I due tipi di eccezione sono distinti intenzionalmente. CloudflareRenderException indica un errore lato Worker e non attiva un nuovo tentativo tramite fallback. CloudflareNotAvailableException indica che l’edge non è stato raggiungibile e che non era disponibile alcun fallback locale.

CloudflareRenderResult è final readonly. I campi seguenti sono popolati dagli header della risposta nel percorso binario, oppure dai campi JSON nel percorso JSON.

MembroOrigine
pdfDataByte PDF grezzi
widthPtLa larghezza richiesta
heightPtHeader X-Pdf-Height-Pt / JSON heightPt; per impostazione predefinita 841.89 (altezza A4) quando il valore è assente o non positivo
contentHeightPxX-Content-Height-Px / JSON contentHeightPx
renderLocationDerivato dal suffisso dell’header CF-Ray (percorso binario) o dal JSON renderLocation
renderTimeMsX-Render-Time-Ms / JSON renderTimeMs
size()strlen($pdfData)
isValid()true quando i byte iniziano con %PDF

Facoltativo — formato carta, font e CSS personalizzati

Sezione intitolata “Facoltativo — formato carta, font e CSS personalizzati”
$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 ha effetto solo quando la configurazione imposta r2FontBucket. Il payload include quindi il nome del bucket e i percorsi dei file di font richiesti, in modo che il Worker possa caricarli.

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

isAvailable() invia un HEAD HTTP autenticato all’URL del Worker. Restituisce true quando lo stato è inferiore a 500. Restituisce false senza sollevare eccezioni quando la configurazione non è valida o la richiesta fallisce. Va considerato un’indicazione, non una garanzia. Il Worker può comunque far fallire la successiva POST.

  • /integrations/cloudflare/production-usage/ — collegamento del fallback, telemetria, archiviazione su R2.
  • /integrations/cloudflare/troubleshooting/ — ogni errore con la relativa eccezione e il messaggio.
  • /integrations/cloudflare/configuration/ — il riferimento completo dei campi.