Salta ai contenuti
getnextpdf.com

Pro edizione

Webview — Riferimento approfondito

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.

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.

Terminal window
composer require nextpdf/pro

Tipi 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.

Una classe final readonly con un costruttore privato; istanziare tramite il costruttore con nome.

  • static fromBytes(string $bytes): self — analizza i byte attraverso la LinearizationView::fromPdf() lato lettura del Core. Solleva UnsupportedDocumentException quando il documento non è linearizzato, quando la /L dichiarata non corrisponde alla lunghezza effettiva in byte, o quando l’offset di fine prima pagina /E non è 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. Solleva RangeNotSatisfiableException solo 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; solleva RangeNotSatisfiableException quando è 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).

Una classe final readonly implementata solo rispetto a PSR-7 / PSR-17.

  • __construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf') — solleva InvalidArgumentException quando $contentType contiene 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’ETag proprio 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’ETag viene derivato dai byte quando è null.
  • firstPageResponse(LinearizedDocument $document): ResponseInterface — costruisce un 206 che trasporta esattamente il byte range della prima pagina; la forma di server-push di “prima pagina prima del download completo”.

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; solleva RangeNotSatisfiableException in caso contrario.
  • length(): int — la campata inclusiva (lastByte - firstByte + 1), sempre >= 1.
  • contentRange(): string — il valore del campo Content-Range RFC 9110 §14.4 bytes first-last/length.

Proprietà readonly pubbliche: firstByte, lastByte, contentLength.

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; restituisce 1.0 per 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.

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:

CondizioneStatoNote
Nessun Range applicabile, oppure If-Range non corrisponde all’attuale ETag forte200 OKCorpo 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 valido200 OKL’header viene ignorato (RFC 9110 §14.2).
Un range soddisfacibile206 Partial ContentTrasporta Content-Range.
Più range soddisfacibili206 Partial Contentmultipart/byteranges con un boundary derivato.
Byte range validi, nessuno soddisfacibile416 Range Not SatisfiableTrasporta 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.

WebviewException è un’interfaccia marcatore che estende Throwable; intercettarla per gestire l’intero sottosistema in modo uniforme. Entrambe le eccezioni concrete la implementano.

  • UnsupportedDocumentException (estende InvalidArgumentException) — sollevata da LinearizedDocument::fromBytes() quando i byte non sono un documento linearizzato utilizzabile. Costruttori con nome: notLinearized() (nessun dizionario di parametri /Linearized), lengthMismatch($declaredLength, $actualLength) (la /L dichiarata non corrisponde alla lunghezza effettiva — troncato, oggetto di append tramite un incremental update oltre /L, o non conforme) e malformedFirstPageOffset($firstPageEndOffset, $length) (l’offset /E non è un offset positivo all’interno del file).
  • RangeNotSatisfiableException (estende OutOfRangeException) — l’errore di slice programmatico, sollevato da ByteRange::__construct() e LinearizedDocument::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.

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.

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.

  • respondToBytes() serve range su byte arbitrari quando la semantica della prima pagina non è necessaria.
  • Un validatore If-Range con data HTTP è trattato come una non corrispondenza → 200 completo (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.

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.