إعداد جسر NextPDF لـ Cloudflare
لمحة سريعة
قسم بعنوان «لمحة سريعة»تتحكم في الحزمة ثلاثة كائنات تكوين غير قابلة للتغيير. تُقرأ كل قيمة افتراضية في هذه الصفحة من توقيع الدالة البانية المقابل في src/Cloudflare/، لا من مواصفة ولا من تقدير. وعندما تذكر هذه الصفحة حدًّا أقصى، فذلك الحدّ قيد تفرضه هذه الحزمة، ولا يمثّل بيانًا عن سعة منصة Cloudflare.
CloudflareRendererConfig
قسم بعنوان «CloudflareRendererConfig»تكوين محرّك العرض. final readonly. أنشئه مباشرةً أو من خلال CloudflareRendererConfig::fromArray().
| الحقل | النوع | الافتراضي | المعنى |
|---|---|---|---|
workerUrl | string | — (مطلوب) | عنوان URL لنقطة نهاية Worker. يجب أن يستخدم HTTPS. |
apiToken | string | — (مطلوب) | رمز Bearer. مميّز بـ #[SensitiveParameter]. |
renderTimeout | int | 30 | مهلة النقل بالثواني، يطبّقها ناقل cURL المثبَّت. |
defaultCss | string | '' | CSS يُحقن في الحمولة قبل HTML الخاص بك. |
maxHtmlSize | int | 5000000 | الحدّ الأقصى لحجم إدخال HTML، بالبايت، ويُفرَض قبل إرسال الطلب. |
r2FontBucket | ?string | null | اسم حاوية R2 لحزم الخطوط المخصصة. |
fallbackToLocal | bool | true | ما إذا كان تعذّر الوصول إلى Worker يؤدي إلى الرجوع إلى محرّك عرض محلي. |
pinnedPublicKeys | list<string> | [] | بصمات SHA-256 SPKI، بالصيغة sha256/<base64>. |
backupPublicKeys | list<string> | [] | تثبيتات SPKI احتياطية، تُحفظ منفصلةً حتى يُتحقَّق من التدوير بصورة مستقلة. |
تُرجع isValid() القيمة true فقط عندما يكون workerUrl !== '' وapiToken !== ''. وتُرجع allPublicKeyPins() اتحاد pinnedPublicKeys وbackupPublicKeys بعد إزالة التكرارات. تقبل طبقة TLS أي شهادة تظهر تجزئة SPKI الخاصة بها في أي عضو من ذلك الاتحاد. يطابق هذا RFC 7469 §2.6، الذي يتحقق من الاتصال المثبَّت عندما تتقاطع مجموعة بصمات SPKI المقدَّمة مع المجموعة المثبَّتة. ويصف RFC 7469 §2.5 التثبيت الاحتياطي بوصفه آلية الاسترداد الأساسية عند حدوث فشل غير مقصود في التحقق من التثبيت. احتفظ بتثبيت احتياطي واحد على الأقل حتى لا يؤدي تدوير الشهادة إلى تعطيل نقطة النهاية — راجع /integrations/cloudflare/security-and-operations/.
خريطة مفاتيح fromArray()
قسم بعنوان «خريطة مفاتيح fromArray()»تقرأ CloudflareRendererConfig::fromArray() مفاتيح snake_case وتطبّق القيم الافتراضية نفسها إذا كان المفتاح غائبًا أو كان نوعه غير صحيح:
| مفتاح المصفوفة | يُطابق |
|---|---|
worker_url | workerUrl |
api_token | apiToken |
render_timeout | renderTimeout (الافتراضي 30) |
default_css | defaultCss |
max_html_size | maxHtmlSize (الافتراضي 5000000) |
r2_font_bucket | r2FontBucket |
fallback_to_local | fallbackToLocal (الافتراضي true) |
pinned_public_keys | pinnedPublicKeys (تُسقَط الأعضاء غير النصية) |
backup_public_keys | backupPublicKeys (تُسقَط الأعضاء غير النصية) |
<?php
declare(strict_types=1);
use NextPDF\Cloudflare\CloudflareRendererConfig;
$config = CloudflareRendererConfig::fromArray([ 'worker_url' => 'https://pdf-renderer.example.workers.dev/render', 'api_token' => getenv('CF_PDF_TOKEN') ?: '', 'render_timeout' => 60, 'r2_font_bucket' => 'pdf-fonts', 'pinned_public_keys' => ['sha256/YLh1dUR9y6Kja30RrAn7JKnbQG/uEtLMkBgFF2Fuihg='], 'backup_public_keys' => ['sha256/Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys='],]);حدود حجم الإدخال التي تفرضها الحزمة
قسم بعنوان «حدود حجم الإدخال التي تفرضها الحزمة»تفرض CloudflareSecurityPolicy::validate() هذه الحدود قبل أن يغادر أي طلب العملية. وتُقرأ الأرقام من المصدر:
| الحدّ | القيمة | الموضع |
|---|---|---|
| الحدّ الأقصى لإدخال HTML | maxHtmlSize (الافتراضي 5000000 بايت) | CloudflareSecurityPolicy::validate() |
| الحدّ الأقصى لحجم data-URI بعد فك ترميزه بـ base64 | 13631488 بايت (≈13 MB) | CloudflareSecurityPolicy::MAX_DATA_URI_BYTES |
يؤدي تجاوز أيٍّ منهما إلى رفع RuntimeException برسالة تذكر الحجم المخالف والحدّ. يعمل الحدّ الأقصى لـ base64 كحاجز ضد قنبلة فكّ الضغط. تقدّر السياسة الحجم بعد فك الترميز من طول base64، وترفض الطلب عند بلوغ الحدّ أو تجاوزه. كما يُرفض وسم <meta http-equiv="refresh">، بصرف النظر عن حالة الأحرف، لأنه يمكنه دفع إعادة توجيه من داخل الصفحة المعروضة.
لا تذكر الحزمة إلا الحدود التي تفرضها بنفسها. وهي لا تقدّم أي ادّعاء بشأن سقوف Worker الخاصة بالطلب أو وحدة المعالجة المركزية أو الذاكرة. راجع وثائق Cloudflare الرسمية وتنفيذ Worker لديك لمعرفة تلك السقوف.
ApiProtectionConfig
قسم بعنوان «ApiProtectionConfig»تكوين طبقة حماية الطلب الاختيارية التي يطبّقها Worker — أو بوابة PHP أمامه — على طلبات العرض الواردة. final readonly.
| الحقل | النوع | الافتراضي | المعنى |
|---|---|---|---|
maxRequestsPerMinute | int | 60 | سقف الطلبات لكل عميل في الدقيقة. |
maxRequestsPerHour | int | 1000 | سقف الطلبات لكل عميل في الساعة. |
maxPayloadSizeBytes | int | 10485760 | الحدّ الأقصى للحمولة الواردة (≈10 MB). |
allowedOrigins | list<string> | [] | قائمة السماح لـ CORS. تعني القيمة الفارغة عدم التصريح بأي قيد على الأصل هنا. |
requireApiKey | bool | true | ما إذا كان مفتاح API مطلوبًا. |
apiKeyHeader | string | 'X-Api-Key' | الترويسة الحاملة لمفتاح API. |
rateLimitWindowSeconds | int | 60 | طول نافذة الدقيقة، بالثواني. |
تقرأ fromArray() max_requests_per_minute، وmax_requests_per_hour، وmax_payload_size_bytes، وallowed_origins، وrequire_api_key، وapi_key_header، وrate_limit_window_seconds. تتطلب isValid() أن يكون كل حقل رقمي موجبًا وأن يكون apiKeyHeader غير فارغ.
R2ArchiveConfig
قسم بعنوان «R2ArchiveConfig»تكوين أرشفة ملفات PDF المعروضة إلى Cloudflare R2 عبر API المتوافق مع S3. final readonly.
| الحقل | النوع | الافتراضي | المعنى |
|---|---|---|---|
bucketName | string | — (مطلوب) | حاوية R2. يُتحقق منها وفق قاعدة تسمية S3. |
accountId | string | — (مطلوب) | معرّف حساب Cloudflare، يُستخدم لبناء نقطة النهاية الافتراضية. |
accessKeyId | string | — (مطلوب) | معرّف مفتاح وصول R2. #[SensitiveParameter]. |
secretAccessKey | string | — (مطلوب) | مفتاح الوصول السري لـ R2. #[SensitiveParameter]. |
endpoint | string | '' | نقطة نهاية S3 مخصصة. تبني القيمة الفارغة الإعداد الافتراضي من accountId. |
pathPrefix | string | 'pdfs/' | بادئة المفتاح للكائنات المرفوعة. |
maxFileSizeBytes | int | 104857600 | الحدّ الأقصى لحجم الرفع (≈100 MB)، يُفرَض قبل الرفع. |
ترفض الدالة البانية أي bucketName غير فارغ لا يطابق القاعدة المتوافقة مع S3. وتنص القاعدة على ما يلي: من 3 إلى 63 حرفًا، من أحرف وأرقام صغيرة وشُرَط، مع البدء والانتهاء بحرف أو رقم. تؤدي المخالفة إلى رفع InvalidArgumentException. تتطلب isValid() أن تكون bucketName، وaccountId، وaccessKeyId، وsecretAccessKey غير فارغة. عندما يكون endpoint فارغًا، تُرجع getEndpoint() القيمة https://<accountId>.r2.cloudflarestorage.com.
معالجة الأسرار
قسم بعنوان «معالجة الأسرار»يحمل apiToken، وaccessKeyId، وsecretAccessKey سمة #[SensitiveParameter]، بحيث يحجب PHP قيمها من آثار المكدس. وفّرها من متغيرات البيئة أو من مدير أسرار، ولا تُودِعها قط في الشيفرة. كائنات التكوين غير قابلة للتغيير؛ فالقيمة التي تُضبط مرةً لا يمكن تغييرها بعد الإنشاء.
انظر أيضًا
قسم بعنوان «انظر أيضًا»- /integrations/cloudflare/quickstart/ — طبّق هذا التكوين في أول عملية عرض.
- /integrations/cloudflare/production-usage/ — الرجوع الاحتياطي وأرشفة R2 وحماية الـ API متصلة معًا.
- /integrations/cloudflare/security-and-operations/ — التثبيت، والدفاع ضد SSRF، وتدوير الأسرار.