Referência da API do Cloudflare
Visão geral
Seção intitulada “Visão geral”O pacote NextPDF\Cloudflare faz a ponte com a renderização na edge. O processo PHP fica responsável pelo Hypertext Markup Language (HTML), e um Cloudflare Worker executa o navegador headless. O pacote expõe um renderer de HTML apoiado por Worker (CloudflareHtmlRenderer) e os value objects que ele retorna, uma camada de proteção de requisições para endpoints de renderização (ApiProtection), um serviço de arquivamento no R2 para arquivos Portable Document Format (PDF) renderizados (R2ArchiveManager) e auxiliares de transporte com pinning para reforçar Transport Layer Security (TLS) e Domain Name System (DNS). A configuração fica em três objetos imutáveis (CloudflareRendererConfig, ApiProtectionConfig, R2ArchiveConfig).
Para começar, monte um CloudflareRendererConfig, conecte-o ao CloudflareHtmlRenderer e chame render(). Essa chamada envia o HTML ao Worker e retorna um CloudflareRenderResult com os bytes do PDF. Proteção, arquivamento e pinning atuam em torno dessa chamada.
Tarefas comuns
Seção intitulada “Tarefas comuns”Estes trechos cobrem os fluxos de trabalho que você provavelmente vai usar com mais frequência. Cada um é autossuficiente, foi verificado contra src/Cloudflare/ e lê os segredos a partir do ambiente.
Renderize uma string de HTML para um PDF na edge com a chamada canônica:
<?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);}O que faz: envia o HTML ao Worker por Hypertext Transfer Protocol Secure (HTTPS) e grava em disco os bytes do PDF A4 retornados depois que isValid() confirma que se trata de um PDF real.
Arquive um PDF renderizado no R2 e retorne um link de curta duração:
<?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;O que faz: envia os bytes do PDF para uma chave do R2 particionada por data e, se a operação for bem-sucedida, cria um uniform resource locator (URL) pré-assinado de 10 minutos para download temporário.
Proteja um endpoint de renderização antes que ele inicie um trabalho caro no Worker:
<?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];}O que faz: valida a chave de API e o tamanho do payload, verifica o limite de taxa por cliente e retorna uma decisão junto com os cabeçalhos de resposta a anexar quando a requisição é negada.
Renderer
Seção intitulada “Renderer”Esta tabela cobre a superfície central do renderer. Use-a quando você constrói a configuração, monta o renderer ou faz chamadas de renderização e de verificação de disponibilidade.
| Símbolo | Parâmetros | Comportamento padrão | Retorno | Lança ou falha com | Notas |
|---|---|---|---|---|---|
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 do Worker, bearer token, timeout, Cascading Style Sheets (CSS), limite de tamanho, bucket de fontes do R2 opcional, flag de fallback, conjuntos de pins. | O fallback local fica habilitado; o pinning permanece desligado quando os arrays de pins estão vazios. | CloudflareRendererConfig | Nenhuma esperada. | Mantenha o token de API em segredo; prefira URLs de worker em HTTPS. |
CloudflareRendererConfig::fromArray(array $config) | worker_url, api_token, render_timeout, default_css, max_html_size, r2_font_bucket, fallback_to_local, arrays de pins. | Chaves opcionais ausentes usam os valores padrão do construtor. | CloudflareRendererConfig | Nenhuma esperada. | Use para arrays de configuração no estilo de framework. |
CloudflareRendererConfig::isValid() | nenhum. | Requer uma URL de worker e um token de API não vazios. | bool | Nenhuma esperada. | Uma configuração inválida aciona o fallback ou faz o renderer falhar. |
CloudflareRendererConfig::allPublicKeyPins() | nenhum. | Combina os pins de chave pública primários e de backup. | list<string> | Nenhuma esperada. | Uma lista vazia desativa o pinning. |
new CloudflareHtmlRenderer(CloudflareRendererConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, ?LoggerInterface $logger = null, ?LocalRendererFactoryInterface $localRendererFactory = null, ?HtmlSecurityPolicyInterface $htmlSecurityPolicy = null, ?ResponseFactoryInterface $responseFactory = null) | Configuração, dependências de Hypertext Transfer Protocol (HTTP) de PHP Standards Recommendation (PSR), logger opcional, factory de fallback local opcional, política de HTML opcional, factory de resposta opcional. | Usa DefaultHtmlSecurityPolicy quando nenhuma política de HTML é fornecida. | CloudflareHtmlRenderer | Erros de wiring do container. | A factory de resposta habilita o transporte cURL com pinning quando necessário. |
CloudflareHtmlRenderer::render(string $html, float $widthPt = 595.28, float $heightPt = 0, array $fontFiles = []) | HTML, largura da página, altura da página, arquivos de fonte no R2. | Largura A4, altura automática, sem arquivos de fonte. | CloudflareRenderResult | CloudflareNotAvailableException, CloudflareRenderException, falhas de validação. | Valida o tamanho do HTML e a URL do worker antes do input/output (I/O) de rede. |
CloudflareHtmlRenderer::getHtmlSecurityPolicy() | nenhum. | Retorna a política configurada da camada de parsing. | HtmlSecurityPolicyInterface | Nenhuma esperada. | Use em conjunto com a proteção de endpoint e a validação da URL do Worker. |
CloudflareHtmlRenderer::isAvailable() | nenhum. | Envia uma requisição HEAD ao worker quando a configuração é válida. | bool | Retorna false em caso de erros. | Use para verificações de prontidão, não como a única proteção em tempo de execução. |
Value objects do renderer e segurança
Seção intitulada “Value objects do renderer e segurança”Use esta tabela para os value objects de requisição e de resultado (CloudflareRenderResult, CloudflareRenderPayload) e para as verificações estáticas da camada de transporte que validam o HTML, a URL do Worker e os pins de DNS antes do I/O de rede.
| Símbolo | Parâmetros | Comportamento padrão | Retorno | Lança ou falha com | Notas |
|---|---|---|---|---|---|
new CloudflareRenderResult(string $pdfData, float $widthPt, float $heightPt, float $contentHeightPx = 0.0, string $renderLocation = '', float $renderTimeMs = 0.0) | Bytes do PDF, largura, altura, altura de conteúdo medida, localização na edge, tempo de renderização. | Os metadados ficam vazios quando o Worker não os reporta. | CloudflareRenderResult | Nenhuma esperada. | Geralmente retornado por CloudflareResponseParser::parse(). |
CloudflareRenderResult::isValid() | nenhum. | Verifica se há bytes de PDF não vazios que começam com um cabeçalho de PDF. | bool | Nenhuma esperada. | Use antes de arquivar ou passar os bytes para outra camada. |
CloudflareRenderResult::size() | nenhum. | Conta os bytes do PDF renderizado. | int | Nenhuma esperada. | Alimente a lógica de cota e de auditoria. |
new CloudflareRenderPayload(string $html, float $widthPt, float $heightPt = 0, string $defaultCss = '', ?string $r2FontBucket = null, array $fontFiles = []) | HTML, tamanho, CSS, bucket de fontes do R2 opcional, lista de arquivos de fonte. | Altura automática, sem CSS padrão, sem bucket de fontes do R2, sem arquivos de fonte. | CloudflareRenderPayload | Nenhuma esperada. | Value object do payload da requisição. |
CloudflareRenderPayload::toJson() | nenhum. | Serializa o HTML, o tamanho, o CSS e as referências de fonte como JavaScript Object Notation (JSON) para o Worker. | string | Erros de codificação de JSON. | API de baixo nível para o payload da requisição. |
CloudflareResponseParser::parse(ResponseInterface $response, float $requestedWidthPt) | Resposta do Worker e largura solicitada. | Aceita respostas de PDF binárias e respostas de JSON estruturadas. | CloudflareRenderResult | CloudflareRenderException para saída do Worker malsucedida ou inválida. | Parser central usado pelo renderer. |
CloudflareSecurityPolicy::validate(string $html, int $maxSize) | Entrada de HTML e limite de tamanho. | Aplica a política de entrada de HTML do pacote. | void | Exceção de validação. | Mantenha as verificações de entrada não confiável fora do limite do Worker. |
CloudflareSecurityPolicy::validateWorkerUrl(string $url) | URL do Worker. | Faz o parsing e valida o destino. | array | Exceção de validação. | Bloqueia formatos inseguros de endpoint antes do I/O de rede. |
CloudflareSecurityPolicy::assertPinsStillValid(string $host, array $pinnedIps) | Host e lista de IPs com pin. | Verifica os pins de DNS esperados. | void | Exceção de validação quando os pins estão desatualizados ou inválidos. | Use durante as verificações operacionais para implantações com pin. |
Proteção da API
Seção intitulada “Proteção da API”Use esta tabela quando você protege um endpoint de renderização: validação de chave de API, verificações de tamanho de payload e de limite de taxa, além dos objetos de resultado e de cabeçalho que elas produzem.
| Símbolo | Parâmetros | Comportamento padrão | Retorno | Lança ou falha com | Notas |
|---|---|---|---|---|---|
new ApiProtection(ApiProtectionConfig $config, ?ApiKeyValidator $keyValidator = null, ?Closure $clock = null) | Configuração de proteção, validador de chave opcional, clock opcional. | Usa o horário do sistema quando nenhum clock é fornecido. | ApiProtection | Nenhuma esperada. | Injete um clock determinístico nos testes. |
ApiProtection::checkRequest(string $clientId, int $payloadSize, string $apiKey = '') | Identificador do cliente, tamanho do payload, chave de API opcional. | Uma chave de API vazia só é permitida quando a configuração não exige chaves. | ApiProtectionResult | Nenhuma esperada. | Verifica a chave de API e o tamanho, depois aplica o limite de taxa. |
ApiProtection::getRateLimit(string $clientId) | Identificador do cliente. | Não registra uma requisição. | RateLimitResult | Nenhuma esperada. | Use para adicionar cabeçalhos de limite de taxa. |
new ApiKeyValidator(array $validKeys = []) | Lista de chaves válidas em texto puro. | Uma lista vazia rejeita todas as chaves. | ApiKeyValidator | Nenhuma esperada. | Armazene os segredos fora do código e hidrate-os por meio da configuração. |
ApiKeyValidator::validate(string $key) | Chave bruta. | Compara com as chaves em texto puro configuradas usando lógica resistente a ataques de tempo. | bool | Nenhuma esperada. | O parâmetro é sensível; não registre chaves brutas em log. |
ApiKeyValidator::addKey(string $key) | Chave bruta. | Adiciona uma chave com hash a uma nova instância do validador. | self | Nenhuma esperada. | Trate a instância retornada como o validador atualizado. |
ApiKeyValidator::revokeKey(string $key) | Chave bruta. | Remove o hash correspondente de uma nova instância do validador. | self | Nenhuma esperada. | Trate a instância retornada como o validador atualizado. |
ApiKeyValidator::hashKey(string $key) | Chave bruta. | Produz a representação de hash armazenada. | string | Nenhuma esperada. | Não exponha hashes em logs ou em respostas ao cliente. |
ApiKeyValidator::validateHashed(string $key, array $hashedKeys) | Chave bruta e hashes candidatos. | Compara com os hashes fornecidos em tempo constante. | bool | Nenhuma esperada. | Auxiliar de baixo nível para armazenamentos de chave personalizados. |
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 requisição, limite de payload, origens permitidas, exigência de chave de API, nome do cabeçalho, duração da janela. | 60/minute, 1000/hour, payload de 10 MiB, chave de API obrigatória. | ApiProtectionConfig | Nenhuma esperada. | Construa diretamente nos testes ou hidrate com 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. | Chaves ausentes usam os valores padrão do construtor. | ApiProtectionConfig | Nenhuma esperada. | Use para hidratar a configuração de framework. |
ApiProtectionConfig::isValid() | nenhum. | Requer limites positivos e valores de tamanho e de janela coerentes. | bool | Nenhuma esperada. | Valide antes de expor um endpoint. |
new ApiProtectionResult(bool $allowed, string $denialReason = '', ?RateLimitResult $rateLimit = null) | Decisão, motivo da negação, resultado de limite de taxa opcional. | Motivo de negação vazio e sem resultado de limite de taxa. | ApiProtectionResult | Nenhuma esperada. | Retornado por ApiProtection::checkRequest(). |
ApiProtectionResult::toHeaders() | nenhum. | Emite cabeçalhos de limite de taxa quando há dados de taxa. | array<string, string> | Nenhuma esperada. | Anexe-os às respostas do Worker ou do framework. |
new RateLimitResult(bool $allowed, int $remainingRequests, int $retryAfterSeconds, string $clientId) | Decisão, contagem restante, atraso de nova tentativa, identificador do cliente (ID). | Sem valores padrão. | RateLimitResult | Nenhuma esperada. | Resultado imutável para uma verificação. |
RateLimitResult::toHeaders() | nenhum. | Emite cabeçalhos de limite restante e de reinício. | array<string, string> | Nenhuma esperada. | Use para observabilidade e backoff do cliente. |
new RateLimitEntry(string $clientId, int $requestCount = 0, int $windowStart = 0, int $hourlyCount = 0, int $hourlyWindowStart = 0) | ID do cliente e contadores mutáveis. | Os contadores começam em zero. | RateLimitEntry | Nenhuma esperada. | Objeto de rastreamento em memória. |
RateLimitEntry::increment() | nenhum. | Incrementa o contador em memória para um client/window. | void | Nenhuma esperada. | Auxiliar de baixo nível usado por ApiProtection. |
RateLimitEntry::isExpired(int $windowSeconds) | Duração da janela em segundos. | Compara com o horário atual. | bool | Nenhuma esperada. | Auxiliar de expiração em tempo de execução. |
RateLimitEntry::isExpiredAt(int $now, int $windowSeconds) | Valor do clock e duração da janela. | Compara com o valor de clock fornecido. | bool | Nenhuma esperada. | Auxiliar de teste determinístico. |
RateLimitEntry::reset() | nenhum. | Reinicia a contagem e o horário de início da janela. | void | Nenhuma esperada. | Usado quando uma nova janela começa. |
Arquivamento no R2
Seção intitulada “Arquivamento no R2”Use esta tabela quando você armazena PDFs renderizados no Cloudflare R2: o serviço de arquivamento, seus tipos de configuração e de object-key, e o resultado de upload que você deve inspecionar antes de expor uma URL.
| Símbolo | Parâmetros | Comportamento padrão | Retorno | Lança ou falha com | Notas |
|---|---|---|---|---|---|
new R2ArchiveManager(R2ArchiveConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory) | Configuração do R2 e factories/client HTTP de PSR. | Nenhuma chamada de rede durante a construção. | R2ArchiveManager | Erros de wiring do container. | Serviço de arquivamento principal. |
R2ArchiveManager::upload(string $pdfData, string $filename, array $metadata = []) | Bytes brutos do PDF, nome de arquivo original, metadados em string. | Metadados vazios; chave particionada por data. | R2UploadResult | Retorna um resultado malsucedido em caso de falha de configuração, de tamanho, de HTTP ou de transporte. | Não lança exceção para falhas normais de upload. |
R2ArchiveManager::generateSignedUrl(string $key, int $expiresInSeconds = 3600) | Chave do objeto e time to live (TTL) da URL. | URL assinada de uma hora. | string | Erros de assinatura decorrentes de configuração inválida. | Use TTLs curtos para PDFs sensíveis. |
R2ArchiveManager::buildObjectKey(string $filename) | Nome de arquivo original. | Usa o prefixo de caminho configurado e a data atual. | R2ObjectKey | Nenhuma esperada. | Use para particionamento de arquivamento previsível. |
R2ArchiveManager::createPutRequest(R2ObjectKey $key, string $data, array $metadata = []) | Chave do objeto, bytes brutos, metadados. | Assina uma requisição PUT. | RequestInterface | Erros de construção da requisição. | API de baixo nível para transportes personalizados. |
new R2ArchiveConfig(string $bucketName, string $accountId, string $accessKeyId, string $secretAccessKey, string $endpoint = '', string $pathPrefix = 'pdfs/', int $maxFileSizeBytes = 104857600) | Bucket, ID da conta, credenciais, substituição de endpoint, prefixo de chave, tamanho máximo de objeto. | Endpoint derivado, prefixo pdfs/, tamanho máximo de objeto de 100 MiB. | R2ArchiveConfig | InvalidArgumentException para nomes de bucket inválidos. | Trate as credenciais como configuração que carrega segredos. |
R2ArchiveConfig::fromArray(array $data) | ID da conta, bucket, credenciais, prefixo de caminho, substituição de endpoint, tamanho máximo. | Valores ausentes usam os valores padrão do construtor. | R2ArchiveConfig | Nome de bucket inválido quando fornecido. | Use para hidratar a configuração da aplicação. |
R2ArchiveConfig::isValid() | nenhum. | Requer conta, bucket, chave de acesso e chave secreta não vazios. | bool | Nenhuma esperada. | Uma configuração inválida faz os uploads falharem com resultados estruturados. |
R2ArchiveConfig::getEndpoint() | nenhum. | Usa um endpoint explícito ou deriva o endpoint do Cloudflare R2 a partir do ID da conta. | string | Nenhuma esperada. | Usado para construir requisições assinadas. |
new R2ObjectKey(string $key, string $bucket) | Chave completa do objeto e bucket. | Sem normalização. | R2ObjectKey | Nenhuma esperada. | Geralmente criado por R2ObjectKey::generate(). |
R2ObjectKey::generate(string $prefix, string $filename, ?DateTimeInterface $date = null) | Prefixo, nome de arquivo original, data opcional. | Chave de objeto particionada por data e sanitizada. | R2ObjectKey | Nenhuma esperada. | Injete a data nos testes para obter chaves determinísticas. |
R2ObjectKey::fullPath() | nenhum. | Junta o caminho da partição e o nome de arquivo do objeto. | string | Nenhuma esperada. | Armazene esse valor como a chave do objeto. |
new R2UploadResult(bool $success, string $key, string $etag = '', int $size = 0, string $error = '') | Flag de sucesso, chave do objeto, entity tag (ETag), tamanho em bytes, mensagem de erro. | ETag vazio, tamanho zero, erro vazio. | R2UploadResult | Nenhuma esperada. | Retornado por R2ArchiveManager::upload(). |
R2UploadResult::isValid() | nenhum. | Válido quando o upload teve sucesso e tanto a chave quanto o ETag estão presentes. | bool | Nenhuma esperada. | Verifique antes de expor URLs. |
R2UploadResult::publicUrl(string $customDomain = '') | Domínio público personalizado opcional. | Retorna a chave do objeto sem formatação quando nenhum domínio personalizado é fornecido. | string | Nenhuma esperada. | Evite URLs públicas para documentos sensíveis, a menos que a política permita. |
Auxiliares de transporte
Seção intitulada “Auxiliares de transporte”Use esta tabela apenas para wiring de baixo nível: pinning de Internet Protocol (IP) e de SubjectPublicKeyInfo (SPKI) no nível do cURL, além dos contratos de renderer local usados como caminho de fallback quando o Worker está inacessível.
| Símbolo | Parâmetros | Comportamento padrão | Retorno | Lança ou falha com | Notas |
|---|---|---|---|---|---|
new PinnedCurlTransport(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, array $pinnedIps = [], array $pinnedPublicKeys = [], int $timeoutSeconds = 30) | Factories de PSR-17, IPs com pin, chaves públicas com pin, timeout. | Sem pins e um timeout de 30 segundos. | PinnedCurlTransport | Nenhuma esperada. | Use somente quando o pinning no nível do cURL for necessário. |
PinnedCurlTransport::sendRequest(RequestInterface $request) | Requisição de PSR-7. | Envia via cURL com o timeout e os controles de pinning configurados. | ResponseInterface | Exceções de transporte de PSR-18. | Use somente quando os clientes HTTP do framework não conseguem aplicar a mesma política de pinning. |
PinnedCurlTransport::buildCurlOptions(RequestInterface $request, string $host, int $port) | Requisição, host de destino, porta de destino. | Monta o array de opções do cURL usado por sendRequest(). | array | Erros de requisição inválida ou de configuração de pin. | Hook de teste e diagnóstico de baixo nível. |
LocalRendererInterface::render(string $html, array $options = []) | HTML e opções do renderer. | Apenas contrato; a implementação define os valores padrão. | string | Erros de renderização específicos da implementação. | Usado como fallback local quando a renderização pelo Worker está indisponível. |
LocalRendererFactoryInterface::create() | nenhum. | Cria uma implementação de renderer local. | LocalRendererInterface | Erros de factory ou de dependência. | Mantém a construção do renderer de fallback fora de CloudflareHtmlRenderer. |
Notas de desenvolvimento
Seção intitulada “Notas de desenvolvimento”- Trate a URL do Worker como um limite de rede. Valide o destino, o tamanho e a autenticação antes de renderizar.
- Use os resultados da proteção de API como saídas de política, não como fluxo de controle por exceção.
- Os uploads no R2 retornam resultados estruturados de sucesso ou de erro; trate ambos os caminhos.