Перейти к содержимому

Обзор моста граничной отрисовки NextPDF для Cloudflare

nextpdf/cloudflare — мост граничной отрисовки. Ваше PHP-приложение хранит HTML, а Cloudflare Worker содержит headless-браузер. Мост отправляет HTML в Worker по HTTPS и получает отрисованные байты PDF. Внутри PHP-процесса headless-браузер не запускается, и мосту не нужен локальный двоичный файл Chromium в управляемом им пути.

Пакет входит в экосистему NextPDF и зависит от nextpdf/core^3.0. Этот код реализует сетевой протокол: формирует JSON-запрос, проверяет входные данные и место назначения, отправляет запрос через PSR-18-клиент и разбирает ответ в типизированный объект результата. Реализация Worker не входит в пакет. Мост взаимодействует с Worker, который развёртываете вы.

Ключевая особенность этого моста в том, что HTML пересекает сетевую границу и попадает в браузерный движок, который вы не контролируете напрямую. Именно из-за этой границы в пакете есть каждое из защитных средств.

  • HTML проверяется до того, как покинет PHP-процесс (CloudflareSecurityPolicy::validate()).
  • URL места назначения проверяется до отправки запроса (CloudflareSecurityPolicy::validateWorkerUrl()), а затем повторно проверяется в момент запроса, чтобы закрыть окно time-of-check/time-of-use (assertPinsStillValid()).
  • Транспорт может закреплять разрешённый набор IP-адресов и открытый ключ сертификата сервера (Transport\PinnedCurlTransport).

Если вы оцениваете этот мост для эксплуатации, прочитайте /integrations/cloudflare/security-and-operations/ перед /integrations/cloudflare/quickstart/. Модель безопасности — не дополнение: она объясняет, почему пакет устроен именно так.

ВозможностьОбеспечивается
Отрисовка HTML в PDF через Cloudflare WorkerCloudflareHtmlRenderer::render()
Проверка доступности (HTTP HEAD)CloudflareHtmlRenderer::isAvailable()
Транспорт, независимый от поставщикаВнедрение ClientInterface PSR-18
Усиление защиты ввода (размер, base64-бомба, meta-refresh)CloudflareSecurityPolicy::validate()
Защита от подделки запросов на стороне сервера (SSRF) и от повторной привязки DNSCloudflareSecurityPolicy::validateWorkerUrl() + assertPinsStillValid()
Закрепление открытого ключа на уровне TLS, закрепление DNS на уровне cURLTransport\PinnedCurlTransport
Резервный переход на локальный Chrome, когда Worker недоступенContract\LocalRendererFactoryInterface
Разбор двоичных и JSON-ответов (base64)CloudflareResponseParser
Граничная телеметрия (время отрисовки, граничная локация, высота содержимого)CloudflareRenderResult
Пользовательские шрифты из R2-бакетаCloudflareRenderPayload (r2FontBucket, fontFiles)
Уровень защиты API (аутентификация по ключу, размер полезной нагрузки, ограничение частоты запросов)ApiProtection
Архивирование PDF в R2 через S3-совместимый APIR2ArchiveManager

Каждая строка соответствует классу в пространстве имён NextPDF\Cloudflare. Каждая строка проверяется по поведению этого класса и его тесту, а не по документу спецификации.

  • Он не запускает браузер. Его запускает Worker.
  • Он не развёртывает и не настраивает ваш Worker. Этот артефакт принадлежит вам.
  • Он не подписывает PDF. Подписание относится к nextpdf/core или коммерческим редакциям. Если требуется подписание, сначала выполните отрисовку, а затем подпишите возвращённые байты движком. NextPDF Pro обеспечивает подписание PAdES B-B. Профили долгосрочной проверки — возможность редакции Enterprise.
  • Он не заявляет какую-либо пропускную способность или лимиты платформы Cloudflare. Единственные ограничения по размеру и времени, указанные в этой документации, — те, которые пакет применяет через собственную конфигурацию (см. /integrations/cloudflare/configuration/).

Мост содержит две разные взаимодополняющие политики. Их смешение — самая распространённая ошибка при анализе. Вот что делает каждая из них.

  • Политика безопасности HTML (HtmlSecurityPolicyInterface, по умолчанию NextPDF\Html\DefaultHtmlSecurityPolicy, предоставляется nextpdf/core): фильтрация содержимого на уровне разбора до того, как содержимое достигнет Worker. Получите её с помощью getHtmlSecurityPolicy().
  • Политика безопасности Cloudflare (CloudflareSecurityPolicy, статическая): задачи транспортного уровня: размер ввода, обнаружение base64-бомбы декомпрессии, блокировка meta-refresh, принудительное использование HTTPS и защита URL-адреса Worker от SSRF и повторной привязки DNS.

Это разделение указано в собственном docblock отрисовщика. Эта страница повторяет его, потому что специалистам, проверяющим эксплуатацию, нужны оба названия на одном экране.

Один вызов render() проходит по этой наблюдаемой последовательности. Она считывается непосредственно из CloudflareHtmlRenderer::render().

  1. Проверка полноты конфигурации (workerUrl и apiToken не пусты). Если проверка не проходит, мост либо переключается на локальный отрисовщик, либо выбрасывает CloudflareNotAvailableException.
  2. Проверка HTML на соответствие настроенному максимальному размеру, верхнему пределу base64 URI и запрету meta-refresh.
  3. Проверка URL-адреса Worker: она разрешает хост и возвращает проверенный набор IP-адресов.
  4. Формирование полезной нагрузки (CloudflareRenderPayload).
  5. Повторная проверка в момент использования подтверждает, что DNS-ответ хоста не изменился с шага 3.
  6. HTTP-запрос POST отправляется через закреплённый транспорт cURL, если есть набор IP-адресов или набор SPKI-закреплений и предоставлена фабрика ResponseFactory PSR-17; иначе — через внедрённый клиент PSR-18.
  7. Ответ разбирается в CloudflareRenderResult.

Любое исключение, кроме CloudflareRenderException, запускает резервный путь. CloudflareRenderException (HTTP-ошибка или некорректный ответ от Worker) повторно выбрасывается без изменений. Это сбой на стороне Worker, а не сбой доступности, поэтому мост не переключается на резервный путь.

  • /integrations/cloudflare/install/ — установка пакета и клиента PSR-18.
  • /integrations/cloudflare/configuration/ — каждое поле конфигурации и его значение по умолчанию, проверенное по исходному коду.
  • /integrations/cloudflare/quickstart/ — ваша первая работоспособная отрисовка.
  • /integrations/cloudflare/production-usage/ — резервный переход, телеметрия, архивирование в R2, защита API.
  • /integrations/cloudflare/security-and-operations/ — эксплуатационные подробности границы доверия.
  • /integrations/cloudflare/troubleshooting/ — режимы сбоев, сопоставленные с исключениями.
  • /integrations/cloudflare/boot-and-discovery/ — как мост подключается к хост-фреймворку.
  • /integrations/cloudflare/integration/ — управление NextPDF через сервисы Cloudflare.