Cloudflare 開發者指南
Cloudflare 套件會將繪製工作移至 Worker 邊界。請將 Worker 繪製、本機後援、API 防護與 R2 封存視為彼此獨立的能力,並分別處理各自的失敗情境。
當你要圍繞 nextpdf/cloudflare 建構邊緣繪製服務、受防護的繪製端點、封存流程或本機後援路徑時,請使用本指南。
架構邊界
標題為「架構邊界」的區段| 層 | 負責方 | 職責 | 不要放在這裡 |
|---|---|---|---|
| 應用程式端點 | 應用程式 | 驗證呼叫端、正規化繪製請求,並落實業務政策。 | 將 Worker token 硬寫在程式碼裡。 |
| API 防護 | nextpdf/cloudflare 與應用程式 | 判定 API key、payload 大小與行程內速率限制。 | 計費、租戶權益,或持久性配額強制。 |
| Cloudflare renderer(渲染器) | nextpdf/cloudflare | 驗證 HTML 與 Worker URL、送出繪製 payload,並剖析回應。 | 範本繪製或網域查詢。 |
| Worker(運算單元) | 應用程式部署 | 執行 Browser Rendering,並回傳 PDF 位元組或結構化結果。 | PHP 端的儲存政策。 |
| 本機後援 | 應用程式部署 | 在 Worker 無法使用時進行繪製。 | 會掩蓋維運中斷的靜默後援。 |
| R2 封存 | nextpdf/cloudflare | 上傳 PDF、建立物件鍵,並建立簽章 URL。 | 未經審查的敏感業務中繼資料。 |
執行期生命週期
標題為「執行期生命週期」的區段| 階段 | 行為 | 開發者動作 |
|---|---|---|
| 組態建立 | 載入 Worker URL、API token、逾時、大小限制、後援與 pin。 | 將祕密資訊放在部署組態中。 |
| 請求防護 | 選用的 ApiProtection 會驗證 key、大小與速率限制。 | 在昂貴的繪製工作開始之前執行。 |
| 呼叫 renderer | CloudflareHtmlRenderer 會驗證 HTML 與 Worker URL,然後送出 JSON。 | 分別處理 Worker 無法使用與繪製失敗的情況。 |
| 剖析回應 | CloudflareResponseParser::parse() 接受二進位 PDF 或結構化 JSON 輸出。 | 拒絕無效或非 PDF 的輸出。 |
| 本機後援 | 選用的本機 renderer 會處理 Worker 失敗。 | 只在主機支援時才注入本機 renderer 工廠。 |
| R2 封存 | R2ArchiveManager 會儲存 PDF 位元組並建立簽章 URL。 | 除非刻意儲存,否則讓中繼資料保持非敏感。 |
建議的應用程式結構
標題為「建議的應用程式結構」的區段| 路徑 | 用途 |
|---|---|
app/Pdf/Cloudflare/* | 位於 CloudflareHtmlRenderer 外側的應用程式包裝層。 |
app/Pdf/Workers/* | Worker 請求 DTO 與端點專屬政策。 |
app/Pdf/Archive/* | R2 封存編排與保留決策。 |
app/Pdf/Fallback/* | LocalRendererFactoryInterface 實作(允許後援時)。 |
tests/Pdf/Cloudflare/* | Worker 中斷、無效 token、payload 與封存等測試。 |
請分開保管 PHP API token 與 Worker token。PHP 端會向 Worker 驗證身分。Worker 在執行瀏覽器工作之前,應先驗證傳入的請求。
<?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());}renderer 模式
標題為「renderer 模式」的區段使用 Framework(框架)提供的 PSR-18 與 PSR-17 依賴項來建構 renderer。讓本機後援保持明確,維運人員才能判斷系統何時不再使用 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);R2 封存模式
標題為「R2 封存模式」的區段只在繪製成功且政策核可後才進行封存。請將公開 URL 與簽章 URL 視為彼此獨立的決策。
<?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);}除非你的保留與存取政策明確允許,否則不要將客戶姓名、電子郵件地址、發票總額或受管制的識別碼放進物件中繼資料。
擴充點
標題為「擴充點」的區段| 擴充點 | 用途 | 限制 |
|---|---|---|
LocalRendererFactoryInterface | 後援至 Artisan 或其他 renderer。 | 必須回傳一個實作 LocalRendererInterface 的物件。 |
ApiProtectionConfig | API key、payload 大小與速率限制政策。 | 記憶體內的限制是以行程為單位。 |
ApiKeyValidator | 時間安全的 key 驗證與 key 輪替輔助工具。 | 將祕密資訊存放在原始程式碼之外。 |
R2ArchiveConfig | bucket、認證憑證、路徑前綴、端點與大小限制。 | 認證憑證絕不可寫入記錄。 |
PinnedCurlTransport | IP 與 SPKI pin 強制。 | 需要支援 cURL 的執行期與回應工廠。 |
CloudflareResponseParser | 剖析 Worker 回應。 | 拒絕無效的 PDF 或錯誤回應。 |
開發工作流程
標題為「開發工作流程」的區段- 先建立本機繪製路徑。
- 使用一份小型且具代表性的 HTML 範例加入 Worker 繪製。
- 在端點對外公開之前,先啟用請求防護。
- 只在繪製與回應流程穩定後才加入 R2 上傳。
- 測試 Worker 中斷、無效 token、超量 payload、速率限制與 R2 失敗等路徑。
- 加入可區分 Worker 繪製、後援繪製、封存上傳與簽章 URL 建立的記錄。
失敗處理
標題為「失敗處理」的區段| 失敗 | 應在何處處理 | 建議的回應方式 |
|---|---|---|
| 缺少或無效的 API key | API 防護層。 | 在繪製工作開始之前就拒絕。 |
| 超量 payload | API 防護或 renderer 驗證。 | 回傳驗證失敗,且不呼叫 Worker。 |
| 不安全的 Worker URL | renderer 的安全政策。 | 在進行網路 I/O 之前,先讓組態或請求失敗。 |
| Worker 無法使用 | renderer 邊界。 | 只在允許時才使用明確的後援;否則就以可觀測的方式失敗。 |
| R2 上傳失敗 | 封存邊界。 | 如果封存是選用項目,則回傳 PDF 回應;如果政策要求必須封存,則讓流程失敗。 |
| pin 輪替失敗 | 部署與維運。 | 搭配備援 pin 與回滾計畫進行輪替。 |
安全的預設值
標題為「安全的預設值」的區段| 考量項目 | 預設值 | 何時應覆寫 |
|---|---|---|
| 後援 | 依組態預設值啟用。 | 當本機繪製會違反部署隔離時,請停用它。 |
| HTML 大小上限 | 5,000,000 位元組。 | 對外公開的端點請調低。 |
| 簽章 URL 的 TTL | 3600 秒。 | 敏感 PDF 請縮短 TTL。 |
| pin 組合 | 空白。 | 只有在備有輪替計畫與備援 pin 時才加入 pin。 |
| API key 需求 | 依防護組態預設值啟用。 | 只有在私有、已通過驗證的內部呼叫時才停用。 |
測試檢查清單
標題為「測試檢查清單」的區段- renderer 測試涵蓋有效 HTML、超量 HTML、無效 Worker URL 與 Worker 錯誤回應。
- API 防護測試涵蓋缺少 key、無效 key、payload 過大與超出速率限制。
- R2 測試涵蓋上傳成功、上傳過大、HTTP 狀態失敗、無效 bucket 與簽章 URL 的產生。
- 後援測試驗證本機 renderer 路徑明確且可觀測。
- 傳輸測試涵蓋已 pin 的 IP、公開金鑰 pin、逾時,以及依政策停用的重新導向。
- 可觀測性測試會斷言繪製、後援、封存與簽章 URL 建立各自有不同的記錄事件。