Pro editie
Webview — Diepe referentie
In het kort
Sectie met titel “In het kort”Deze pagina documenteert het publieke NextPDF\Pro\Webview-oppervlak, het byte-range request-/responsemodel en de exacte faalmodi die verder gaan dan de publieke landingspagina.
Beschikbaarheid en licentie
Sectie met titel “Beschikbaarheid en licentie”Deze mogelijkheid wordt geleverd in NextPDF Pro (nextpdf/pro) en wordt geactiveerd met een Pro-tier-licentie-envelope. Een deployment zonder die entitlement laadt de klassen van de mogelijkheid niet. Vergelijk edities en vraag een licentie aan.
Er is geen licentievlag per feature; de code wordt geleverd met de Pro-editie. De PSR-17-ResponseFactoryInterface / StreamFactoryInterface en het body-media-type zijn runtime-constructorparameters, geen licentiebesturing.
Publiek API-oppervlak
Sectie met titel “Publiek API-oppervlak”composer require nextpdf/proPublieke typen onder NextPDF\Pro\Webview:
LinearizedDocument— een gevalideerde gelineariseerde PDF, klaar voor aflevering.ByteRangeResponder— de RFC 9110 byte-range-HTTP-responder.ByteRange— één bevredigbare inclusieve byte-range over een representatie.FirstPageProber— het structurele “eerste pagina vóór de volledige download”-bewijs.
Exception-typen onder NextPDF\Pro\Webview\Exception:
WebviewException(marker-interface),UnsupportedDocumentException,RangeNotSatisfiableException.
LinearizedDocument
Sectie met titel “LinearizedDocument”Een final readonly-klasse met een private constructor; instantieer via de named constructor.
static fromBytes(string $bytes): self— parseert de bytes via de read-sideLinearizationView::fromPdf()van Core. WerptUnsupportedDocumentExceptionwanneer het document niet gelineariseerd is, wanneer de gedeclareerde/Lniet overeenkomt met de werkelijke bytelengte, of wanneer de/E-end-of-first-page-offset geen positieve offset binnen het bestand is.length(): int— de documentlengte in bytes.firstPagePrefixLength(): int— de minimale leidende prefix die de complete eerste pagina bevat: de/E-offset, geklemd op de bestandslengte.firstPageByteRange(): ByteRange— de inclusieve range[0, /E - 1]die de eerste pagina aflevert. WerptRangeNotSatisfiableExceptionalleen als de prefix leeg is (defence-in-depth;fromBytes()garandeert al0 < /E <= length).slice(int $firstByte, int $lastByte): string— strikte programmatische slice met inclusieve offsets; werptRangeNotSatisfiableExceptionbij buiten-bereik.etag(): string— de sterke, deterministische SHA-256-entity-tag voor de bytes, eenmalig gememoïseerd bij constructie.
Publieke readonly properties: bytes (de ruwe PDF-bytes) en view (de Core-LinearizationView).
ByteRangeResponder
Sectie met titel “ByteRangeResponder”Een final readonly-klasse die uitsluitend tegen PSR-7 / PSR-17 is geïmplementeerd.
__construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf')— werptInvalidArgumentExceptionwanneer$contentTypecontrol characters bevat (het wordt geïnterpoleerd in response- en multipart-part-headers; CR/LF en andere control bytes worden afgewezen om header-injectie te voorkomen).respond(LinearizedDocument $document, ServerRequestInterface $request): ResponseInterface— beantwoordt een range-request voor een gelineariseerd document, met gebruik van de eigenETagvan het document.respondToBytes(string $bytes, ServerRequestInterface $request, ?string $etag = null): ResponseInterface— beantwoordt een range-request voor willekeurige bytes (een representatie die ranges moet ondersteunen zonder gelineariseerd te zijn). DeETagwordt uit de bytes afgeleid wanneernull.firstPageResponse(LinearizedDocument $document): ResponseInterface— bouwt een206die exact de byte-range van de eerste pagina draagt; de server-push-vorm van “eerste pagina vóór de volledige download”.
ByteRange
Sectie met titel “ByteRange”Een final readonly value object voor één bevredigbare inclusieve byte-range (RFC 9110 §14.1.2).
__construct(int $firstByte, int $lastByte, int $contentLength)— dwingt bevredigbaarheid0 <= firstByte <= lastByte <= contentLength - 1af; werpt andersRangeNotSatisfiableException.length(): int— de inclusieve span (lastByte - firstByte + 1), altijd>= 1.contentRange(): string— de RFC 9110 §14.4Content-Range-veldwaardebytes first-last/length.
Publieke readonly properties: firstByte, lastByte, contentLength.
FirstPageProber
Sectie met titel “FirstPageProber”Een final readonly-klasse, geconstrueerd uit een LinearizedDocument.
prefixLength(): int— het minimale leidende aantal bytes dat nodig is om de eerste pagina te renderen.prefixFraction(): float— de fractie van het hele bestand (0.0–1.0) die de prefix vertegenwoordigt; retourneert1.0voor een bestand met lengte nul.hintStreamWithinPrefix(): bool— of het primaire hint-stream-object volledig binnen de first-page-prefix ligt (zodat de prefix alleen een lezer pagina-1-objecten laat lokaliseren). De hint stream moet een positieve lengte hebben.isFirstPageSelfContained(): bool— het gecombineerde structurele bewijs: een positieve prefix die binnen het bestand past en de hint stream volledig bevat.
Byte-range request-/responsemodel
Sectie met titel “Byte-range request-/responsemodel”ByteRangeResponder volgt RFC 9110 §14. Na het berekenen van de lengte en een sterke SHA-256-ETag leest het de Range- en If-Range-headers en beslist het:
| Conditie | Status | Opmerkingen |
|---|---|---|
Geen toepasselijke Range, of If-Range komt niet overeen met de huidige sterke ETag | 200 OK | Volledige body. Alleen de sterke-entity-tag-vorm van If-Range wordt gehonoreerd (RFC 9110 §13.1.5). |
Niet-herkende range-unit of syntactisch ongeldige Range | 200 OK | De header wordt genegeerd (RFC 9110 §14.2). |
| Eén bevredigbare range | 206 Partial Content | Draagt Content-Range. |
| Meerdere bevredigbare ranges | 206 Partial Content | multipart/byteranges met een afgeleide boundary. |
| Geldige byte-ranges, geen enkele bevredigbaar | 416 Range Not Satisfiable | Draagt Content-Range: bytes */length (RFC 9110 §15.3.7). |
Elke response adverteert Accept-Ranges: bytes en de sterke ETag. 200- en 206-responses stellen ook Content-Type en Content-Length in.
Range-parsing accepteert alleen de bytes=-unit. Het ondersteunt expliciet first-last, open-eind first- (geklemd op het einde), en suffix -N (de laatste N bytes; een suffix dat minstens zo groot is als de representatie selecteert het geheel ervan). Een kale - (of elke anderszins misvormde spec) maakt de hele Range-header syntactisch ongeldig, zodat de header wordt genegeerd en de volledige 200 OK-representatie wordt geretourneerd. Een -0-suffix, of elke spec waarvan de eerste offset op of voorbij het einde ligt, is een onbevredigbare spec en wordt weggelaten; als geen enkele spec in de header bevredigbaar is, is de response 416 Range Not Satisfiable. Grote decimale offsets worden vergeleken zonder te vertrouwen op integer-overflow-saturatie, zodat een 30-cijferige Range-waarde platformonafhankelijk wordt afgehandeld. Overlappende bevredigbare ranges worden samengevoegd voordat er een body wordt gebouwd; werkelijk distincte (niet-overlappende) ranges worden behouden als afzonderlijke multipart parts.
Faalmodi en exception-model
Sectie met titel “Faalmodi en exception-model”WebviewException is een marker-interface die Throwable uitbreidt; vang het op om het hele subsysteem uniform af te handelen. Beide concrete exceptions implementeren het.
UnsupportedDocumentException(breidtInvalidArgumentExceptionuit) — geworpen doorLinearizedDocument::fromBytes()wanneer de bytes geen bruikbaar gelineariseerd document zijn. Named constructors:notLinearized()(geen/Linearized-parameter-dictionary),lengthMismatch($declaredLength, $actualLength)(de gedeclareerde/Lkomt niet overeen met de werkelijke lengte — afgekapt, uitgebreid via een incrementele update voorbij/L, of niet-conform), enmalformedFirstPageOffset($firstPageEndOffset, $length)(de/E-offset is geen positieve offset binnen het bestand).RangeNotSatisfiableException(breidtOutOfRangeExceptionuit) — de programmatische-slice-fout, geworpen doorByteRange::__construct()enLinearizedDocument::slice()/firstPageByteRange()wanneer een inclusieve range buiten het document valt. Named constructor:outOfBounds($firstByte, $lastByte, $length).
De HTTP-responder werpt geen RangeNotSatisfiableException voor client-Range-headers — een onbevredigbare HTTP-range is een 416-response (RFC 9110 §15.3.7), geen exception. Die exception is gereserveerd voor directe programmatische slicing, waar een buiten-bereik-request een caller-fout is. ByteRangeResponder::__construct() werpt een gewone InvalidArgumentException (geen WebviewException) wanneer de geconfigureerde contentType control characters bevat.
Denial-of-service-hardening
Sectie met titel “Denial-of-service-hardening”De responder begrenst het aantal distincte samengevoegde ranges dat per request wordt gehonoreerd (de multipart-range-amplification-klasse, Apache HTTPD CVE-2011-3192). Wanneer een request om meer dan de cap aan samengevoegde ranges vraagt, of om meer totale bytes dan de hele representatie, wordt de Range genegeerd en wordt een volledige 200 geretourneerd. De multipart boundary wordt deterministisch afgeleid en opnieuw afgeleid totdat het gegarandeerd niet binnen de body voorkomt, wat reproduceerbare uitvoer behoudt en tegelijk boundary-collisie uitsluit.
Conformiteit
Sectie met titel “Conformiteit”Byte-range-gedrag volgt RFC 9110 (HTTP Semantics): §14 (range-requests), §13.1.5 (If-Range), §14.4 (Content-Range) en §15.3.7 (416). De gelineariseerde-documentopmaak is het Fast Web View-model van ISO 32000-2 Annex F. De module beweert geen verdere externe clausule-identifiers buiten gedrag dat door zijn tests is geverifieerd.
Randgevallen en FIPS-modusgedrag
Sectie met titel “Randgevallen en FIPS-modusgedrag”respondToBytes()bedient ranges over willekeurige bytes wanneer first-page-semantiek niet nodig is.- Een
If-Rangemet een HTTP-date-validator wordt als een non-match behandeld → volledige200(de client haalt simpelweg opnieuw op). - De
ETagis een SHA-256-hash die puur als sterke cache-validator wordt gebruikt; deze module voert geen ondertekening of andere cryptografische bewerkingen uit en definieert geen FIPS-specifiek gedrag.
Publicatiegrens
Sectie met titel “Publicatiegrens”Deze pagina documenteert uitsluitend extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helper-klassen, mechanisme-tabellen, runbook-bestandsnamen en ticket-prefixen vallen buiten de scope.