Ga naar inhoud
getnextpdf.com

Pro editie

Webview — Diepe referentie

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.

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.

Terminal window
composer require nextpdf/pro

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

Een final readonly-klasse met een private constructor; instantieer via de named constructor.

  • static fromBytes(string $bytes): self — parseert de bytes via de read-side LinearizationView::fromPdf() van Core. Werpt UnsupportedDocumentException wanneer het document niet gelineariseerd is, wanneer de gedeclareerde /L niet 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. Werpt RangeNotSatisfiableException alleen als de prefix leeg is (defence-in-depth; fromBytes() garandeert al 0 < /E <= length).
  • slice(int $firstByte, int $lastByte): string — strikte programmatische slice met inclusieve offsets; werpt RangeNotSatisfiableException bij 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).

Een final readonly-klasse die uitsluitend tegen PSR-7 / PSR-17 is geïmplementeerd.

  • __construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf') — werpt InvalidArgumentException wanneer $contentType control 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 eigen ETag van 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). De ETag wordt uit de bytes afgeleid wanneer null.
  • firstPageResponse(LinearizedDocument $document): ResponseInterface — bouwt een 206 die exact de byte-range van de eerste pagina draagt; de server-push-vorm van “eerste pagina vóór de volledige download”.

Een final readonly value object voor één bevredigbare inclusieve byte-range (RFC 9110 §14.1.2).

  • __construct(int $firstByte, int $lastByte, int $contentLength) — dwingt bevredigbaarheid 0 <= firstByte <= lastByte <= contentLength - 1 af; werpt anders RangeNotSatisfiableException.
  • length(): int — de inclusieve span (lastByte - firstByte + 1), altijd >= 1.
  • contentRange(): string — de RFC 9110 §14.4 Content-Range-veldwaarde bytes first-last/length.

Publieke readonly properties: firstByte, lastByte, contentLength.

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; retourneert 1.0 voor 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.

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:

ConditieStatusOpmerkingen
Geen toepasselijke Range, of If-Range komt niet overeen met de huidige sterke ETag200 OKVolledige body. Alleen de sterke-entity-tag-vorm van If-Range wordt gehonoreerd (RFC 9110 §13.1.5).
Niet-herkende range-unit of syntactisch ongeldige Range200 OKDe header wordt genegeerd (RFC 9110 §14.2).
Eén bevredigbare range206 Partial ContentDraagt Content-Range.
Meerdere bevredigbare ranges206 Partial Contentmultipart/byteranges met een afgeleide boundary.
Geldige byte-ranges, geen enkele bevredigbaar416 Range Not SatisfiableDraagt 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.

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 (breidt InvalidArgumentException uit) — geworpen door LinearizedDocument::fromBytes() wanneer de bytes geen bruikbaar gelineariseerd document zijn. Named constructors: notLinearized() (geen /Linearized-parameter-dictionary), lengthMismatch($declaredLength, $actualLength) (de gedeclareerde /L komt niet overeen met de werkelijke lengte — afgekapt, uitgebreid via een incrementele update voorbij /L, of niet-conform), en malformedFirstPageOffset($firstPageEndOffset, $length) (de /E-offset is geen positieve offset binnen het bestand).
  • RangeNotSatisfiableException (breidt OutOfRangeException uit) — de programmatische-slice-fout, geworpen door ByteRange::__construct() en LinearizedDocument::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.

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.

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.

  • respondToBytes() bedient ranges over willekeurige bytes wanneer first-page-semantiek niet nodig is.
  • Een If-Range met een HTTP-date-validator wordt als een non-match behandeld → volledige 200 (de client haalt simpelweg opnieuw op).
  • De ETag is 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.

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.