Skip to content

Cloudflare developer guide

The Cloudflare package moves Portable Document Format (PDF) rendering to a Worker boundary. Treat Worker rendering, local fallback, application programming interface (API) protection, and the R2 archive as separate capabilities, each with its own failure handling.

Use this guide when you build edge-rendering services, protected render endpoints, archive workflows, or local fallback paths with nextpdf/cloudflare.

LayerOwned byResponsibilityDo not put here
Application endpointApplicationAuthorize the caller, normalize the render request, and enforce business policy.Worker tokens stored in code.
API protectionnextpdf/cloudflare and applicationAPI key checks, payload size checks, and in-process rate-limit decisions.Billing, tenant entitlement, or durable quota enforcement.
Cloudflare renderernextpdf/cloudflareValidate Hypertext Markup Language (HTML) and the Worker Uniform Resource Locator (URL), send the render payload, and parse the response.Template rendering or domain queries.
WorkerApplication deploymentRun Browser Rendering and return PDF bytes or a structured result.PHP-side storage policy.
Local fallbackApplication deploymentRender when the Worker is unavailable.Silent fallback that hides operational outages.
R2 archivenextpdf/cloudflareUpload PDF files, build object keys, and create signed URLs.Sensitive business metadata without review.
StageBehaviorDeveloper action
Config creationLoads the Worker URL, API token, timeouts, size limits, fallback, and pins.Keep secrets in deployment config.
Request protectionOptional ApiProtection validates the key, size, and rate limit.Run it before expensive render work.
Renderer callCloudflareHtmlRenderer validates HTML and the Worker URL, then sends JavaScript Object Notation (JSON).Handle Worker unavailability and render failures separately.
Response parsingCloudflareResponseParser::parse() accepts binary PDF output or structured JSON output.Reject invalid or non-PDF output.
Local fallbackAn optional local renderer handles Worker failure.Inject a local renderer factory only when the host supports it.
R2 archiveR2ArchiveManager stores PDF bytes and creates signed URLs.Keep metadata non-sensitive unless you intentionally store it.
PathPurpose
app/Pdf/Cloudflare/*Application wrapper for CloudflareHtmlRenderer.
app/Pdf/Workers/*Worker request data transfer objects (DTOs) and endpoint-specific policy.
app/Pdf/Archive/*R2 archive orchestration and retention decisions.
app/Pdf/Fallback/*LocalRendererFactoryInterface implementation for allowed fallback.
tests/Pdf/Cloudflare/*Worker-down, invalid-token, payload, and archive tests.

Keep the PHP API token separate from the Worker token. PHP authenticates to the Worker. The Worker should authenticate incoming requests before it starts browser work.

<?php
use NextPDF\Cloudflare\ApiProtection;
use NextPDF\Cloudflare\ApiProtectionConfig;
use NextPDF\Cloudflare\ApiKeyValidator;
$protection = new ApiProtection(
new ApiProtectionConfig(maxRequestsPerMinute: 30),
new ApiKeyValidator([$expectedApiKey]),
);
$result = $protection->checkRequest(
clientId: $clientId,
payloadSize: strlen($html),
apiKey: $presentedApiKey,
);
if (!$result->allowed) {
return new JsonResponse(['error' => $result->denialReason], 429, $result->toHeaders());
}

Build the renderer with PHP Standards Recommendation (PSR) dependencies, including PSR-18 and PSR-17, from your framework. Keep local fallback explicit so operators can see when the system stops using the Worker.

<?php
use NextPDF\Cloudflare\CloudflareHtmlRenderer;
use NextPDF\Cloudflare\CloudflareRendererConfig;
$renderer = new CloudflareHtmlRenderer(
config: CloudflareRendererConfig::fromArray([
'worker_url' => getenv('NEXTPDF_CLOUDFLARE_WORKER_URL'),
'api_token' => getenv('NEXTPDF_CLOUDFLARE_API_TOKEN'),
'render_timeout' => 30,
'max_html_size' => 1_000_000,
'fallback_to_local' => false,
]),
httpClient: $httpClient,
requestFactory: $requestFactory,
streamFactory: $streamFactory,
);
$rendered = $renderer->render($html, widthPt: 595.28);

Archive only after rendering succeeds and policy approves the result. Treat public URLs and signed URLs as separate decisions.

<?php
use NextPDF\Cloudflare\R2ArchiveManager;
$upload = $archive->upload(
pdfData: $rendered->pdfData,
filename: 'invoice-1234.pdf',
metadata: [
'document_type' => 'invoice',
],
);
if ($upload->isValid()) {
$temporaryUrl = $archive->generateSignedUrl($upload->key, 600);
}

Do not put customer names, email addresses, invoice totals, or regulated identifiers in object metadata unless your retention and access policy explicitly allows it.

Extension pointUse it forConstraint
LocalRendererFactoryInterfaceLocal fallback through Artisan or another renderer.Must return an object that implements LocalRendererInterface.
ApiProtectionConfigAPI key, payload size, and rate-limit policy.In-memory limits apply per process.
ApiKeyValidatorTiming-safe key validation and key rotation helpers.Store secrets outside source code.
R2ArchiveConfigBucket, credentials, path prefix, endpoint, and size limits.Credentials must never be logged.
PinnedCurlTransportInternet Protocol (IP) and Subject Public Key Info (SPKI) pin enforcement.Requires a cURL-capable runtime and response factory.
CloudflareResponseParserWorker response parsing.Rejects invalid PDF output or error responses.
  1. Build a local render path first.
  2. Add Worker rendering with a small representative HTML fixture.
  3. Enable request protection before exposing public endpoints.
  4. Add R2 upload only after the render and response flows are stable.
  5. Test Worker-down, invalid-token, oversize-payload, rate-limit, and R2-failure paths.
  6. Add logs that distinguish Worker render, fallback render, archive upload, and signed URL creation.
FailureWhere it should be handledRecommended response
Missing or invalid API keyAPI protection layer.Reject the request before render work starts.
Oversize payloadAPI protection or renderer validation.Return a validation failure with no Worker call.
Unsafe Worker URLRenderer security policy.Fail configuration or the request before network input/output (I/O).
Worker unavailableRenderer boundary.Use explicit fallback only when allowed; otherwise fail visibly.
R2 upload failureArchive boundary.Return the PDF response if archive is optional; fail if archive is required by policy.
Pin rotation failureDeployment and operations.Rotate with backup pins and a rollback plan.
ConcernDefaultWhen to override
FallbackEnabled by config default.Disable when local rendering would violate deployment isolation.
Max HTML size5,000,000 bytes.Lower for public endpoints.
Signed URL time to live (TTL)3600 seconds.Shorten it for sensitive PDFs.
Pin setsEmpty.Add pins only with a rotation plan and backup pins.
API key requirementEnabled by protection config default.Disable only for private, already-authenticated internal calls.
  • Renderer tests cover valid HTML, oversize HTML, invalid Worker URL, and a Worker error response.
  • API protection tests cover a missing key, an invalid key, a payload that is too large, and an exceeded rate limit.
  • R2 tests cover successful upload, too-large upload, failed Hypertext Transfer Protocol (HTTP) status, invalid bucket, and signed URL generation.
  • Fallback tests verify the local renderer path is explicit and observable.
  • Transport tests cover pinned IPs, public-key pins, timeout, and redirects disabled by policy.
  • Observability tests assert distinct log events for render, fallback, archive, and signed URL creation.