Pro edisi
Webview — Referensi Mendalam
Sekilas pandang
Bagian berjudul “Sekilas pandang”Halaman ini mendokumentasikan permukaan publik NextPDF\Pro\Webview, model permintaan/respons byte-range, dan mode kegagalan yang persis di luar halaman landing publik.
Ketersediaan & lisensi
Bagian berjudul “Ketersediaan & lisensi”Kapabilitas ini disertakan dalam NextPDF Pro (nextpdf/pro) dan aktif dengan envelope lisensi tier Pro. Deployment tanpa entitlement tersebut tidak memuat kelas-kelas kapabilitas ini. Bandingkan edisi dan dapatkan lisensi.
Tidak ada flag lisensi per-fitur; kodenya disertakan bersama edisi Pro. PSR-17 ResponseFactoryInterface / StreamFactoryInterface dan media type body adalah parameter konstruktor runtime, bukan kontrol lisensi.
Permukaan API publik
Bagian berjudul “Permukaan API publik”composer require nextpdf/proTipe publik di bawah NextPDF\Pro\Webview:
LinearizedDocument— PDF terlinearisasi yang tervalidasi dan disiapkan untuk pengiriman.ByteRangeResponder— responder HTTP byte-range RFC 9110.ByteRange— satu byte range inklusif yang dapat dipenuhi atas sebuah representasi.FirstPageProber— pembuktian struktural “halaman pertama sebelum pengunduhan penuh”.
Tipe eksepsi di bawah NextPDF\Pro\Webview\Exception:
WebviewException(marker interface),UnsupportedDocumentException,RangeNotSatisfiableException.
LinearizedDocument
Bagian berjudul “LinearizedDocument”Sebuah kelas final readonly dengan konstruktor privat; instansiasikan melalui named constructor.
static fromBytes(string $bytes): self— mem-parsing byte melaluiLinearizationView::fromPdf()sisi-baca milik Core. MemunculkanUnsupportedDocumentExceptionketika dokumen tidak terlinearisasi, ketika/Lyang dideklarasikan tidak cocok dengan panjang byte sebenarnya, atau ketika offset akhir-halaman-pertama/Ebukan offset positif di dalam berkas.length(): int— panjang dokumen dalam byte.firstPagePrefixLength(): int— prefiks awal minimal yang memuat halaman pertama lengkap: offset/E, dijepit ke panjang berkas.firstPageByteRange(): ByteRange— range inklusif[0, /E - 1]yang mengirimkan halaman pertama. MemunculkanRangeNotSatisfiableExceptionhanya jika prefiks kosong (pertahanan berlapis;fromBytes()sudah menjamin0 < /E <= length).slice(int $firstByte, int $lastByte): string— slice programatik ketat dengan offset inklusif; memunculkanRangeNotSatisfiableExceptionketika di luar batas.etag(): string— entity-tag SHA-256 yang kuat dan deterministik untuk byte, di-memoise sekali saat konstruksi.
Properti readonly publik: bytes (byte PDF mentah) dan view (Core LinearizationView).
ByteRangeResponder
Bagian berjudul “ByteRangeResponder”Sebuah kelas final readonly yang diimplementasikan hanya terhadap PSR-7 / PSR-17.
__construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf')— memunculkanInvalidArgumentExceptionketika$contentTypemengandung karakter kontrol (ia di-interpolasi ke dalam header respons dan header part multipart; CR/LF dan byte kontrol lainnya ditolak untuk mencegah header injection).respond(LinearizedDocument $document, ServerRequestInterface $request): ResponseInterface— menjawab permintaan range untuk dokumen terlinearisasi, menggunakanETagmilik dokumen itu sendiri.respondToBytes(string $bytes, ServerRequestInterface $request, ?string $etag = null): ResponseInterface— menjawab permintaan range untuk byte arbitrer (representasi yang seharusnya mendukung range tanpa harus terlinearisasi).ETagditurunkan dari byte ketikanull.firstPageResponse(LinearizedDocument $document): ResponseInterface— membangun sebuah206yang membawa persis byte range halaman pertama; bentuk server-push dari “halaman pertama sebelum pengunduhan penuh”.
ByteRange
Bagian berjudul “ByteRange”Sebuah value object final readonly untuk satu byte range inklusif yang dapat dipenuhi (RFC 9110 §14.1.2).
__construct(int $firstByte, int $lastByte, int $contentLength)— menegakkan satisfiability0 <= firstByte <= lastByte <= contentLength - 1; memunculkanRangeNotSatisfiableExceptionjika tidak.length(): int— rentang inklusif (lastByte - firstByte + 1), selalu>= 1.contentRange(): string— nilai fieldContent-RangeRFC 9110 §14.4bytes first-last/length.
Properti readonly publik: firstByte, lastByte, contentLength.
FirstPageProber
Bagian berjudul “FirstPageProber”Sebuah kelas final readonly yang dibangun dari sebuah LinearizedDocument.
prefixLength(): int— jumlah byte awal minimal yang dibutuhkan untuk me-render halaman pertama.prefixFraction(): float— fraksi keseluruhan berkas (0.0–1.0) yang diwakili prefiks; mengembalikan1.0untuk berkas berpanjang-nol.hintStreamWithinPrefix(): bool— apakah objek primary hint stream sepenuhnya berada di dalam prefiks halaman-pertama (sehingga prefiks saja memungkinkan pembaca menemukan objek halaman-1). Hint stream harus memiliki panjang positif.isFirstPageSelfContained(): bool— pembuktian struktural gabungan: prefiks positif yang muat di dalam berkas dan sepenuhnya memuat hint stream.
Model permintaan/respons byte-range
Bagian berjudul “Model permintaan/respons byte-range”ByteRangeResponder mengikuti RFC 9110 §14. Setelah menghitung panjang dan ETag SHA-256 yang kuat, ia membaca header Range dan If-Range lalu memutuskan:
| Kondisi | Status | Catatan |
|---|---|---|
Tidak ada Range yang berlaku, atau If-Range tidak cocok dengan ETag kuat saat ini | 200 OK | Body penuh. Hanya bentuk entity-tag kuat dari If-Range yang dihormati (RFC 9110 §13.1.5). |
Unit range tak dikenali atau Range cacat secara sintaks | 200 OK | Header diabaikan (RFC 9110 §14.2). |
| Satu range yang dapat dipenuhi | 206 Partial Content | Membawa Content-Range. |
| Beberapa range yang dapat dipenuhi | 206 Partial Content | multipart/byteranges dengan boundary yang diturunkan. |
| Byte range valid, tidak ada yang dapat dipenuhi | 416 Range Not Satisfiable | Membawa Content-Range: bytes */length (RFC 9110 §15.3.7). |
Setiap respons mengiklankan Accept-Ranges: bytes dan ETag kuat. Respons 200 dan 206 juga menyetel Content-Type dan Content-Length.
Parsing range hanya menerima unit bytes=. Ia mendukung first-last eksplisit, first- terbuka (dijepit ke akhir), dan suffix -N (N byte terakhir; suffix yang setidaknya sebesar representasi memilih keseluruhannya). Sebuah - telanjang (atau spec cacat lainnya) membuat keseluruhan header Range cacat secara sintaks, sehingga header diabaikan dan representasi 200 OK penuh dikembalikan. Suffix -0, atau spec apa pun yang offset pertamanya berada pada atau melampaui akhir, adalah spec yang tak dapat dipenuhi dan dibuang; jika tidak ada spec di dalam header yang dapat dipenuhi, responsnya adalah 416 Range Not Satisfiable. Offset desimal besar dibandingkan tanpa mengandalkan saturasi integer-overflow, sehingga nilai Range 30-digit ditangani secara platform-independent. Range yang dapat dipenuhi dan tumpang-tindih digabungkan sebelum body apa pun dibangun; range yang benar-benar berbeda (tidak tumpang-tindih) dipertahankan sebagai part multipart terpisah.
Mode kegagalan & model eksepsi
Bagian berjudul “Mode kegagalan & model eksepsi”WebviewException adalah marker interface yang memperluas Throwable; tangkap ia untuk menangani keseluruhan subsistem secara seragam. Kedua eksepsi konkret mengimplementasikannya.
UnsupportedDocumentException(memperluasInvalidArgumentException) — dimunculkan olehLinearizedDocument::fromBytes()ketika byte bukan dokumen terlinearisasi yang dapat digunakan. Named constructor:notLinearized()(tanpa dictionary parameter/Linearized),lengthMismatch($declaredLength, $actualLength)(/Lyang dideklarasikan tidak cocok dengan panjang sebenarnya — terpotong, ditambahi melalui incremental update melampaui/L, atau non-konforman), danmalformedFirstPageOffset($firstPageEndOffset, $length)(offset/Ebukan offset positif di dalam berkas).RangeNotSatisfiableException(memperluasOutOfRangeException) — galat slice programatik, dimunculkan olehByteRange::__construct()danLinearizedDocument::slice()/firstPageByteRange()ketika range inklusif jatuh di luar dokumen. Named constructor:outOfBounds($firstByte, $lastByte, $length).
Responder HTTP tidak memunculkan RangeNotSatisfiableException untuk header Range klien — range HTTP yang tak dapat dipenuhi adalah respons 416 (RFC 9110 §15.3.7), bukan eksepsi. Eksepsi itu disediakan untuk slicing programatik langsung, di mana permintaan di luar batas adalah galat pemanggil. ByteRangeResponder::__construct() memunculkan InvalidArgumentException biasa (bukan WebviewException) ketika contentType yang dikonfigurasi mengandung karakter kontrol.
Pengerasan denial-of-service
Bagian berjudul “Pengerasan denial-of-service”Responder membatasi jumlah range gabungan berbeda yang dihormati per permintaan (kelas range-amplification multipart, Apache HTTPD CVE-2011-3192). Ketika sebuah permintaan meminta lebih dari batas range gabungan, atau lebih banyak total byte daripada keseluruhan representasi, Range diabaikan dan sebuah 200 penuh dikembalikan. Boundary multipart diturunkan secara deterministik dan diturunkan ulang sampai dijamin tidak muncul di dalam body, mempertahankan keluaran yang dapat direproduksi sambil meniadakan tabrakan boundary.
Kesesuaian
Bagian berjudul “Kesesuaian”Perilaku byte-range mengikuti RFC 9110 (HTTP Semantics): §14 (permintaan range), §13.1.5 (If-Range), §14.4 (Content-Range), dan §15.3.7 (416). Tata letak dokumen-terlinearisasi adalah model Fast Web View dari ISO 32000-2 Annex F. Modul tidak menyatakan pengenal klausa eksternal lebih lanjut di luar perilaku yang diverifikasi oleh pengujiannya.
Kasus tepi & perilaku mode FIPS
Bagian berjudul “Kasus tepi & perilaku mode FIPS”respondToBytes()menyajikan range atas byte arbitrer ketika semantik halaman-pertama tidak dibutuhkan.- Validator
If-Rangeberformat HTTP-date diperlakukan sebagai non-match →200penuh (klien cukup mengambil ulang). ETagadalah hash SHA-256 yang digunakan murni sebagai validator cache yang kuat; modul ini tidak melakukan penandatanganan atau operasi kriptografis lainnya dan tidak mendefinisikan perilaku spesifik-FIPS.
Batas publikasi
Bagian berjudul “Batas publikasi”Halaman ini hanya mendokumentasikan perilaku yang dapat diamati secara eksternal dan permukaan API publik yang didukung. Path namespace internal, kelas helper, tabel mekanisme, nama berkas runbook, dan prefiks tiket berada di luar cakupan.