Pro edizione
Webview — Riferimento approfondito
In breve
Sezione intitolata “In breve”Questa pagina documenta la superficie pubblica NextPDF\Pro\Webview, il modello di richiesta/risposta byte-range e le esatte modalità di fallimento oltre a quanto illustrato nella pagina di destinazione pubblica.
Disponibilità e licenza
Sezione intitolata “Disponibilità e licenza”Questa funzionalità è inclusa in NextPDF Pro (nextpdf/pro) e si attiva con un envelope di licenza di livello Pro. Un deployment privo di tale entitlement non carica le classi della funzionalità. Confronta le edizioni e ottieni una licenza.
Non esiste alcun flag di licenza per singola funzionalità; il codice è distribuito con l’edizione Pro. Le ResponseFactoryInterface / StreamFactoryInterface PSR-17 e il media type del corpo sono parametri del costruttore di runtime, non controlli di licenza.
Superficie API pubblica
Sezione intitolata “Superficie API pubblica”composer require nextpdf/proTipi pubblici sotto NextPDF\Pro\Webview:
LinearizedDocument— un PDF linearizzato convalidato e preparato per il recapito.ByteRangeResponder— il responder HTTP byte-range RFC 9110.ByteRange— un singolo byte range inclusivo soddisfacibile su una rappresentazione.FirstPageProber— la prova strutturale “prima pagina prima del download completo”.
Tipi di eccezione sotto NextPDF\Pro\Webview\Exception:
WebviewException(interfaccia marcatore),UnsupportedDocumentException,RangeNotSatisfiableException.
LinearizedDocument
Sezione intitolata “LinearizedDocument”Una classe final readonly con un costruttore privato; istanziare tramite il costruttore con nome.
static fromBytes(string $bytes): self— analizza i byte attraverso laLinearizationView::fromPdf()lato lettura del Core. SollevaUnsupportedDocumentExceptionquando il documento non è linearizzato, quando la/Ldichiarata non corrisponde alla lunghezza effettiva in byte, o quando l’offset di fine prima pagina/Enon è un offset positivo all’interno del file.length(): int— la lunghezza del documento in byte.firstPagePrefixLength(): int— il prefisso iniziale minimo che contiene la prima pagina completa: l’offset/E, ridotto alla lunghezza del file.firstPageByteRange(): ByteRange— il range inclusivo[0, /E - 1]che recapita la prima pagina. SollevaRangeNotSatisfiableExceptionsolo se il prefisso è vuoto (difesa in profondità;fromBytes()garantisce già0 < /E <= length).slice(int $firstByte, int $lastByte): string— slice programmatico strict con offset inclusivi; sollevaRangeNotSatisfiableExceptionquando è fuori dai limiti.etag(): string— l’entity-tag SHA-256 forte e deterministico per i byte, memoizzato una sola volta alla costruzione.
Proprietà readonly pubbliche: bytes (i byte grezzi del PDF) e view (la LinearizationView del Core).
ByteRangeResponder
Sezione intitolata “ByteRangeResponder”Una classe final readonly implementata solo rispetto a PSR-7 / PSR-17.
__construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf')— sollevaInvalidArgumentExceptionquando$contentTypecontiene caratteri di controllo (viene interpolato negli header della risposta e delle parti multipart; CR/LF e altri byte di controllo vengono rifiutati per prevenire l’header injection).respond(LinearizedDocument $document, ServerRequestInterface $request): ResponseInterface— risponde a una richiesta di range per un documento linearizzato, usando l’ETagproprio del documento.respondToBytes(string $bytes, ServerRequestInterface $request, ?string $etag = null): ResponseInterface— risponde a una richiesta di range per byte arbitrari (una rappresentazione che dovrebbe supportare i range senza essere linearizzata). L’ETagviene derivato dai byte quando ènull.firstPageResponse(LinearizedDocument $document): ResponseInterface— costruisce un206che trasporta esattamente il byte range della prima pagina; la forma di server-push di “prima pagina prima del download completo”.
ByteRange
Sezione intitolata “ByteRange”Un value object final readonly per un singolo byte range inclusivo soddisfacibile (RFC 9110 §14.1.2).
__construct(int $firstByte, int $lastByte, int $contentLength)— impone la soddisfacibilità0 <= firstByte <= lastByte <= contentLength - 1; sollevaRangeNotSatisfiableExceptionin caso contrario.length(): int— la campata inclusiva (lastByte - firstByte + 1), sempre>= 1.contentRange(): string— il valore del campoContent-RangeRFC 9110 §14.4bytes first-last/length.
Proprietà readonly pubbliche: firstByte, lastByte, contentLength.
FirstPageProber
Sezione intitolata “FirstPageProber”Una classe final readonly costruita a partire da un LinearizedDocument.
prefixLength(): int— il numero minimo di byte iniziali necessari per renderizzare la prima pagina.prefixFraction(): float— la frazione dell’intero file (0.0–1.0) che il prefisso rappresenta; restituisce1.0per un file di lunghezza zero.hintStreamWithinPrefix(): bool— se l’oggetto del primary hint stream giace interamente all’interno del prefisso della prima pagina (così che il solo prefisso consenta a un lettore di localizzare gli oggetti della pagina 1). Il hint stream deve avere lunghezza positiva.isFirstPageSelfContained(): bool— la prova strutturale combinata: un prefisso positivo che rientra nel file e contiene interamente il hint stream.
Modello di richiesta/risposta byte-range
Sezione intitolata “Modello di richiesta/risposta byte-range”ByteRangeResponder segue RFC 9110 §14. Dopo aver calcolato la lunghezza e un ETag SHA-256 forte, legge gli header Range e If-Range e decide:
| Condizione | Stato | Note |
|---|---|---|
Nessun Range applicabile, oppure If-Range non corrisponde all’attuale ETag forte | 200 OK | Corpo completo. Viene onorata solo la forma con entity-tag forte di If-Range (RFC 9110 §13.1.5). |
Unità di range non riconosciuta o Range sintatticamente non valido | 200 OK | L’header viene ignorato (RFC 9110 §14.2). |
| Un range soddisfacibile | 206 Partial Content | Trasporta Content-Range. |
| Più range soddisfacibili | 206 Partial Content | multipart/byteranges con un boundary derivato. |
| Byte range validi, nessuno soddisfacibile | 416 Range Not Satisfiable | Trasporta Content-Range: bytes */length (RFC 9110 §15.3.7). |
Ogni risposta pubblicizza Accept-Ranges: bytes e l’ETag forte. Le risposte 200 e 206 impostano anche Content-Type e Content-Length.
Il parsing dei range accetta solo l’unità bytes=. Supporta first-last esplicito, first- aperto (ridotto alla fine) e suffisso -N (gli ultimi N byte; un suffisso grande almeno quanto la rappresentazione seleziona l’intera rappresentazione). Un - nudo (o qualsiasi altra specifica malformata) rende l’intero header Range sintatticamente non valido, così l’header viene ignorato e viene restituita la rappresentazione 200 OK completa. Un suffisso -0, o qualsiasi specifica il cui primo offset sia al limite o oltre la fine, è una specifica non soddisfacibile e viene scartata; se nessuna specifica nell’header è soddisfacibile la risposta è 416 Range Not Satisfiable. Gli offset decimali grandi vengono confrontati senza affidarsi alla saturazione da integer-overflow, così un valore Range di 30 cifre viene gestito in modo indipendente dalla piattaforma. I range soddisfacibili sovrapposti vengono unificati prima che venga costruito qualsiasi corpo; i range genuinamente distinti (non sovrapposti) vengono preservati come parti multipart separate.
Modalità di fallimento e modello delle eccezioni
Sezione intitolata “Modalità di fallimento e modello delle eccezioni”WebviewException è un’interfaccia marcatore che estende Throwable; intercettarla per gestire l’intero sottosistema in modo uniforme. Entrambe le eccezioni concrete la implementano.
UnsupportedDocumentException(estendeInvalidArgumentException) — sollevata daLinearizedDocument::fromBytes()quando i byte non sono un documento linearizzato utilizzabile. Costruttori con nome:notLinearized()(nessun dizionario di parametri/Linearized),lengthMismatch($declaredLength, $actualLength)(la/Ldichiarata non corrisponde alla lunghezza effettiva — troncato, oggetto di append tramite un incremental update oltre/L, o non conforme) emalformedFirstPageOffset($firstPageEndOffset, $length)(l’offset/Enon è un offset positivo all’interno del file).RangeNotSatisfiableException(estendeOutOfRangeException) — l’errore di slice programmatico, sollevato daByteRange::__construct()eLinearizedDocument::slice()/firstPageByteRange()quando un range inclusivo cade al di fuori del documento. Costruttore con nome:outOfBounds($firstByte, $lastByte, $length).
Il responder HTTP non solleva RangeNotSatisfiableException per gli header Range del client — un range HTTP non soddisfacibile è una risposta 416 (RFC 9110 §15.3.7), non un’eccezione. Quell’eccezione è riservata allo slicing programmatico diretto, dove una richiesta fuori dai limiti è un errore del chiamante. ByteRangeResponder::__construct() solleva una semplice InvalidArgumentException (non una WebviewException) quando il contentType configurato contiene caratteri di controllo.
Hardening contro il denial-of-service
Sezione intitolata “Hardening contro il denial-of-service”Il responder limita il numero di range distinti coalescenti onorati per richiesta (la classe della multipart range-amplification, Apache HTTPD CVE-2011-3192). Quando una richiesta chiede più del limite di range coalescenti, o più byte totali dell’intera rappresentazione, il Range viene ignorato e viene restituito un 200 completo. Il boundary multipart viene derivato in modo deterministico e ri-derivato finché non è garantito non comparire all’interno del corpo, preservando un output riproducibile pur escludendo la collisione del boundary.
Conformità
Sezione intitolata “Conformità”Il comportamento byte-range segue RFC 9110 (HTTP Semantics): §14 (richieste di range), §13.1.5 (If-Range), §14.4 (Content-Range) e §15.3.7 (416). La disposizione del documento linearizzato è il modello Fast Web View di ISO 32000-2 Annex F. Il modulo non asserisce ulteriori identificatori di clausola esterni oltre al comportamento verificato dai suoi test.
Casi limite e comportamento in modalità FIPS
Sezione intitolata “Casi limite e comportamento in modalità FIPS”respondToBytes()serve range su byte arbitrari quando la semantica della prima pagina non è necessaria.- Un validatore
If-Rangecon data HTTP è trattato come una non corrispondenza →200completo (il client semplicemente rifà il fetch). - L’
ETagè un hash SHA-256 usato puramente come validatore di cache forte; questo modulo non esegue alcuna firma o altra operazione crittografica e non definisce alcun comportamento specifico per FIPS.
Confine di pubblicazione
Sezione intitolata “Confine di pubblicazione”Questa pagina documenta solo il comportamento osservabile esternamente e la superficie API pubblica supportata. I percorsi di namespace interni, le classi helper, le tabelle dei meccanismi, i nomi dei file di runbook e i prefissi dei ticket sono fuori ambito.