跳到內容

Cloudflare API 參考

這個 NextPDF\Cloudflare 套件是邊緣渲染橋接層:你的 PHP 程式持有 HTML,Cloudflare Worker 則持有無頭瀏覽器。這個套件對外提供以 Worker 為後端的 HTML renderer(CloudflareHtmlRenderer)及其回傳值物件、用來守護渲染 endpoint 的請求防護層(ApiProtection)、用來儲存已渲染 PDF 的 R2 封存服務(R2ArchiveManager),以及用於 TLS/DNS 強化的固定式傳輸輔助工具。組態則存放在三個不可變物件中(CloudflareRendererConfigApiProtectionConfigR2ArchiveConfig)。

建議從這裡開始:如果你剛接觸這個套件,先建立一個 CloudflareRendererConfig,接到 CloudflareHtmlRenderer,再呼叫 render()。這次呼叫會把你的 HTML 送到 Worker,並回傳帶有 PDF 位元組的 CloudflareRenderResult。其餘所有功能(防護、封存、固定)都圍繞這次呼叫疊加。

以下程式片段示範這個套件最常見的實務工作流程。每一段都可獨立運作,已對照 src/Cloudflare/ 原始碼驗證,並會從環境變數讀取密鑰。

在邊緣將一段 HTML 字串渲染成 PDF——這是唯一的標準渲染呼叫:

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

作用:透過 HTTPS 將 HTML 送到 Worker,並在 isValid() 確認它是真正的 PDF 後,把回傳的 A4 PDF 位元組寫入磁碟。

將已渲染的 PDF 封存到 R2,並回傳一個短效連結:

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

作用:將 PDF 位元組上傳到依日期分區的 R2 鍵;成功後產生一個 10 分鐘的預先簽署 URL,供暫時下載。

在執行昂貴的 Worker 工作之前,先對渲染 endpoint 做防護:

<?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];
}

作用:依序驗證 API 金鑰、酬載大小,以及每個用戶端的速率上限;回傳單一決策,以及請求被拒時要附帶的回應標頭。

renderer 表格列出核心介面。當你要建構組態、建立 renderer,或發出渲染與可用性檢查呼叫時,請使用這張表。

符號參數預設行為回傳擲出或失敗於備註
new CloudflareRendererConfig(string $workerUrl, string $apiToken, int $renderTimeout = 30, string $defaultCss = '', int $maxHtmlSize = 5000000, ?string $r2FontBucket = null, bool $fallbackToLocal = true, array $pinnedPublicKeys = [], array $backupPublicKeys = [])Worker URL、bearer token、逾時、CSS、大小上限、選用的 R2 字型 bucket、fallback 旗標與 pin 集合。預設啟用本機 fallback;pin 陣列為空時停用固定。CloudflareRendererConfig預期無。妥善保管 API token;優先使用 HTTPS 的 worker URL。
CloudflareRendererConfig::fromArray(array $config)worker_urlapi_tokenrender_timeoutdefault_cssmax_html_sizer2_font_bucketfallback_to_local、pin 陣列。未提供的選用鍵採用建構式預設值。CloudflareRendererConfig預期無。對應 Framework(框架)風格的組態陣列。
CloudflareRendererConfig::isValid()無。需要非空的 worker URL 與 API token。bool預期無。無效組態會在 renderer 中觸發 fallback 或失敗。
CloudflareRendererConfig::allPublicKeyPins()無。合併主要公開金鑰 pin 與備援公開金鑰 pin。list<string>預期無。空清單會停用固定。
new CloudflareHtmlRenderer(CloudflareRendererConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory, ?LoggerInterface $logger = null, ?LocalRendererFactoryInterface $localRendererFactory = null, ?HtmlSecurityPolicyInterface $htmlSecurityPolicy = null, ?ResponseFactoryInterface $responseFactory = null)組態、PSR HTTP 相依項、選用的 logger、選用的本機 fallback 工廠、選用的 HTML 政策與選用的 response 工廠。未提供 HTML 政策時,會使用 DefaultHtmlSecurityPolicyCloudflareHtmlRenderercontainer(容器)接線錯誤。需要時,response 工廠會啟用固定式 cURL 傳輸。
CloudflareHtmlRenderer::render(string $html, float $widthPt = 595.28, float $heightPt = 0, array $fontFiles = [])HTML、頁面寬度、頁面高度、R2 中的字型檔。A4 寬度、自動高度、無字型檔。CloudflareRenderResultCloudflareNotAvailableExceptionCloudflareRenderException、驗證失敗。網路 I/O 前會先驗證 HTML 大小與 worker URL。
CloudflareHtmlRenderer::getHtmlSecurityPolicy()無。回傳已設定的剖析層政策。HtmlSecurityPolicyInterface預期無。與 endpoint 防護及 Worker URL 驗證搭配使用。
CloudflareHtmlRenderer::isAvailable()無。組態有效時,會對 worker 發出 HEAD 請求。bool發生錯誤時回傳 false用於就緒檢查,不應作為唯一的執行期防線。

當你需要 request/result 值物件(CloudflareRenderResultCloudflareRenderPayload),或需要用靜態傳輸層檢查在任何網路 I/O 前驗證 HTML、Worker URL 與 DNS pin 時,請使用這張表。

符號參數預設行為回傳擲出或失敗於備註
new CloudflareRenderResult(string $pdfData, float $widthPt, float $heightPt, float $contentHeightPx = 0.0, string $renderLocation = '', float $renderTimeMs = 0.0)PDF 位元組、寬度、高度、測得的內容高度、邊緣位置、渲染時間。Worker 未回報時,中繼資料留空。CloudflareRenderResult預期無。通常由 CloudflareResponseParser::parse() 回傳。
CloudflareRenderResult::isValid()無。檢查 PDF 位元組是否非空,且是否以 PDF 標頭開頭。bool預期無。在封存或把位元組傳給其他層之前使用。
CloudflareRenderResult::size()無。計算已渲染 PDF 的位元組數。int預期無。把這個值送入配額與稽核邏輯。
new CloudflareRenderPayload(string $html, float $widthPt, float $heightPt = 0, string $defaultCss = '', ?string $r2FontBucket = null, array $fontFiles = [])HTML、尺寸、CSS、選用的 R2 字型 bucket 與字型檔清單。自動高度、無預設 CSS、無 R2 字型 bucket、無字型檔。CloudflareRenderPayload預期無。請求酬載值物件。
CloudflareRenderPayload::toJson()無。將 HTML、尺寸、CSS 與字型參照序列化給 Worker。stringJSON 編碼錯誤。底層的請求酬載 API。
CloudflareResponseParser::parse(ResponseInterface $response, float $requestedWidthPt)Worker 回應與請求的寬度。接受二進位 PDF 回應與結構化 JSON 回應。CloudflareRenderResultCloudflareRenderException:當 Worker 輸出失敗或無效時擲出。renderer 使用的中央 parser(剖析器)。
CloudflareSecurityPolicy::validate(string $html, int $maxSize)HTML 輸入與大小上限。套用套件的 HTML 輸入政策。void驗證例外。將不受信任的輸入檢查放在 Worker 邊界之外。
CloudflareSecurityPolicy::validateWorkerUrl(string $url)Worker URL(網址)。剖析並驗證目的地。array驗證例外。在網路 I/O 之前阻擋不安全的 endpoint 形式。
CloudflareSecurityPolicy::assertPinsStillValid(string $host, array $pinnedIps)主機與固定的 IP 清單。驗證 DNS pin 是否符合預期值。voidpin 過期或無效時擲出驗證例外。在固定式部署的維運檢查期間使用。

當你要守護渲染 endpoint 時,請使用這張表:API 金鑰驗證、酬載大小與速率上限檢查,以及它們產生的 result/header 物件。

符號參數預設行為回傳擲出或失敗於備註
new ApiProtection(ApiProtectionConfig $config, ?ApiKeyValidator $keyValidator = null, ?Closure $clock = null)防護組態、選用的金鑰驗證器、選用的時鐘。未提供時鐘時,使用系統時間。ApiProtection預期無。在測試中注入決定性的時鐘。
ApiProtection::checkRequest(string $clientId, int $payloadSize, string $apiKey = '')用戶端識別碼、酬載大小、選用的 API 金鑰。只有在組態不要求金鑰時,才允許空的 API 金鑰。ApiProtectionResult預期無。依序檢查 API 金鑰與大小,再檢查速率上限。
ApiProtection::getRateLimit(string $clientId)用戶端識別碼。不會記錄一次請求。RateLimitResult預期無。用來加入速率上限標頭。
new ApiKeyValidator(array $validKeys = [])有效金鑰的明文清單。空清單會拒絕所有金鑰。ApiKeyValidator預期無。將密鑰存放在程式碼之外,並透過組態載入。
ApiKeyValidator::validate(string $key)原始金鑰。與已設定的明文金鑰做時序安全比對。bool預期無。敏感參數;不要記錄原始金鑰。
ApiKeyValidator::addKey(string $key)原始金鑰。將雜湊後的金鑰加入新的驗證器實例。self預期無。將回傳的實例當成更新後的驗證器。
ApiKeyValidator::revokeKey(string $key)原始金鑰。在新的驗證器實例中移除相符的雜湊。self預期無。將回傳的實例當成更新後的驗證器。
ApiKeyValidator::hashKey(string $key)原始金鑰。產生用於儲存的雜湊表示。string預期無。不要在日誌或用戶端回應中曝露雜湊。
ApiKeyValidator::validateHashed(string $key, array $hashedKeys)原始金鑰與候選雜湊。與提供的雜湊做常數時間比對。bool預期無。供自訂金鑰儲存使用的底層輔助方法。
new ApiProtectionConfig(int $maxRequestsPerMinute = 60, int $maxRequestsPerHour = 1000, int $maxPayloadSizeBytes = 10485760, array $allowedOrigins = [], bool $requireApiKey = true, string $apiKeyHeader = 'X-Api-Key', int $rateLimitWindowSeconds = 60)請求上限、酬載上限、允許的來源、API 金鑰需求、標頭名稱與視窗長度。60/minute、1000/hour、10 MiB 酬載、需要 API 金鑰。ApiProtectionConfig預期無。在測試中直接建構,或透過 fromArray() 載入。
ApiProtectionConfig::fromArray(array $data)max_requests_per_minutemax_requests_per_hourmax_payload_size_bytesallowed_originsrequire_api_keyapi_key_headerrate_limit_window_seconds未提供的鍵採用建構式預設值。ApiProtectionConfig預期無。用於框架組態載入。
ApiProtectionConfig::isValid()無。需要正數上限,以及一致的 size/window 值。bool預期無。在對外開放 endpoint 之前先驗證。
new ApiProtectionResult(bool $allowed, string $denialReason = '', ?RateLimitResult $rateLimit = null)決策、拒絕原因與選用的速率上限結果。拒絕原因為空,且無速率上限結果。ApiProtectionResult預期無。ApiProtection::checkRequest() 回傳。
ApiProtectionResult::toHeaders()無。有速率資料時,輸出速率上限標頭。array<string, string>預期無。附加到 worker 或框架回應。
new RateLimitResult(bool $allowed, int $remainingRequests, int $retryAfterSeconds, string $clientId)決策、剩餘次數、重試延遲與用戶端 ID。無預設值。RateLimitResult預期無。單次檢查產生的不可變結果。
RateLimitResult::toHeaders()無。輸出剩餘上限與重設標頭。array<string, string>預期無。用於可觀測性與用戶端退避。
new RateLimitEntry(string $clientId, int $requestCount = 0, int $windowStart = 0, int $hourlyCount = 0, int $hourlyWindowStart = 0)用戶端 ID 與可變計數器。計數器從零開始。RateLimitEntry預期無。記憶體內的追蹤物件。
RateLimitEntry::increment()無。為單一 client/window 遞增記憶體內計數器。void預期無。ApiProtection 使用的底層輔助方法。
RateLimitEntry::isExpired(int $windowSeconds)以秒為單位的視窗長度。與目前時間比較。bool預期無。執行期的逾期輔助方法。
RateLimitEntry::isExpiredAt(int $now, int $windowSeconds)時鐘值與視窗長度。與提供的時鐘值比較。bool預期無。決定性的測試輔助方法。
RateLimitEntry::reset()無。重設計數與視窗起始時間。void預期無。在新視窗開始時使用。

當你要將已渲染的 PDF 儲存到 Cloudflare R2 時,請使用這張表:封存服務、其組態與物件鍵型別,以及在對外開放 URL 前要檢查的上傳結果。

符號參數預設行為回傳擲出或失敗於備註
new R2ArchiveManager(R2ArchiveConfig $config, ClientInterface $httpClient, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory)R2 組態與 PSR HTTP factories/client。建構期間不會發出網路呼叫。R2ArchiveManager容器接線錯誤。主要的封存服務。
R2ArchiveManager::upload(string $pdfData, string $filename, array $metadata = [])原始 PDF 位元組、原始檔名與字串中繼資料。中繼資料為空;鍵依日期分區。R2UploadResult組態、大小、HTTP 或傳輸失敗時,回傳不成功的結果。一般上傳失敗時不會擲出例外。
R2ArchiveManager::generateSignedUrl(string $key, int $expiresInSeconds = 3600)物件鍵與 URL TTL。有效一小時的簽署 URL。string無效組態造成的簽署錯誤。敏感 PDF 應維持較短的 TTL。
R2ArchiveManager::buildObjectKey(string $filename)原始檔名。使用設定好的路徑前綴與目前日期。R2ObjectKey預期無。用於可預期的封存分區。
R2ArchiveManager::createPutRequest(R2ObjectKey $key, string $data, array $metadata = [])物件鍵、原始位元組與中繼資料。簽署 PUT 請求。RequestInterface請求建構錯誤。供自訂傳輸使用的底層 API。
new R2ArchiveConfig(string $bucketName, string $accountId, string $accessKeyId, string $secretAccessKey, string $endpoint = '', string $pathPrefix = 'pdfs/', int $maxFileSizeBytes = 104857600)bucket、帳戶 ID、憑證、endpoint 覆寫值、鍵前綴與物件大小上限。推導出的 endpoint、pdfs/ 前綴與 100 MiB 物件大小上限。R2ArchiveConfigInvalidArgumentException:當 bucket 名稱無效時擲出。將憑證視為帶有密鑰的組態。
R2ArchiveConfig::fromArray(array $data)帳戶 ID、bucket、憑證、路徑前綴、endpoint 覆寫值與大小上限。未提供的值採用建構式預設值。R2ArchiveConfig提供時,若 bucket 名稱無效。用於應用程式組態載入。
R2ArchiveConfig::isValid()無。需要非空的帳戶、bucket、存取金鑰與密鑰。bool預期無。無效組態會讓上傳以結構化結果失敗。
R2ArchiveConfig::getEndpoint()無。使用明確指定的 endpoint,或從帳戶 ID 推導出 Cloudflare R2 endpoint。string預期無。用於建構簽署請求。
new R2ObjectKey(string $key, string $bucket)完整物件鍵與 bucket。不進行正規化。R2ObjectKey預期無。通常由 R2ObjectKey::generate() 建立。
R2ObjectKey::generate(string $prefix, string $filename, ?DateTimeInterface $date = null)前綴、原始檔名與選用的日期。產生依日期分區且已清理的物件鍵。R2ObjectKey預期無。在測試中注入日期,以取得決定性的鍵。
R2ObjectKey::fullPath()無。接合分區路徑與物件檔名。string預期無。把這個值儲存為物件鍵。
new R2UploadResult(bool $success, string $key, string $etag = '', int $size = 0, string $error = '')成功旗標、物件鍵、ETag、位元組大小與錯誤訊息。ETag 為空、大小為零、錯誤為空。R2UploadResult預期無。R2ArchiveManager::upload() 回傳。
R2UploadResult::isValid()無。上傳成功且鍵與 ETag 都存在時,視為有效。bool預期無。在對外開放 URL 之前先檢查。
R2UploadResult::publicUrl(string $customDomain = '')選用的自訂公開網域。未提供自訂網域時,回傳裸物件鍵。string預期無。除非政策允許,否則避免對敏感文件使用公開 URL。

這張表只用於底層接線:cURL 層級的 IP/SPKI 固定,以及 Worker 無法連線時作為 fallback 路徑的本機 renderer 契約。

符號參數預設行為回傳擲出或失敗於備註
new PinnedCurlTransport(ResponseFactoryInterface $responseFactory, StreamFactoryInterface $streamFactory, array $pinnedIps = [], array $pinnedPublicKeys = [], int $timeoutSeconds = 30)PSR-17 工廠、固定的 IP、固定的公開金鑰與逾時。無 pin,逾時 30 秒。PinnedCurlTransport預期無。只在需要 cURL 層級固定時使用。
PinnedCurlTransport::sendRequest(RequestInterface $request)PSR-7 請求。透過 cURL 以設定好的逾時與固定控制送出。ResponseInterfacePSR-18 傳輸例外。只在框架的 HTTP 用戶端無法強制執行同等固定政策時使用。
PinnedCurlTransport::buildCurlOptions(RequestInterface $request, string $host, int $port)請求、目標主機與目標連接埠。建構 sendRequest() 使用的 cURL 選項陣列。array無效的請求或錯誤的 pin 設定。底層的測試與診斷掛鉤。
LocalRendererInterface::render(string $html, array $options = [])HTML 與 renderer 選項。僅作為契約;預設值由實作決定。string實作各自定義的渲染錯誤。Worker 渲染無法使用時,作為本機 fallback 使用。
LocalRendererFactoryInterface::create()無。建立一個本機 renderer 實作。LocalRendererInterface工廠或相依項錯誤。把 fallback renderer 的建構工作移出 CloudflareHtmlRenderer
  • 將 Worker URL 視為一個網路邊界。渲染之前,先驗證目的地、大小與身分驗證。
  • 將 API 防護結果當成政策輸出,而不是例外控制流程。
  • R2 上傳會回傳結構化的成功或錯誤結果;兩條路徑都必須處理。