Pro édition
Webview — Référence approfondie
Cette page documente la surface publique NextPDF\Pro\Webview, le modèle requête/réponse par plage d’octets et les modes de défaillance exacts, au-delà de la page d’accueil publique.
Disponibilité et licence
Section intitulée « Disponibilité et licence »Cette capacité est livrée dans NextPDF Pro (nextpdf/pro) et s’active avec une enveloppe de licence de palier Pro. Un déploiement sans ce droit ne charge pas les classes de la capacité. Compare les éditions et obtiens une licence.
Il n’y a pas d’indicateur de licence par fonctionnalité ; le code est livré avec l’édition Pro. Les ResponseFactoryInterface / StreamFactoryInterface PSR-17 et le type de média du corps sont des paramètres de constructeur au runtime, non des contrôles de licence.
Surface d’API publique
Section intitulée « Surface d’API publique »composer require nextpdf/proTypes publics sous NextPDF\Pro\Webview :
LinearizedDocument— un PDF linéarisé validé, préparé pour la livraison.ByteRangeResponder— le responder HTTP par plage d’octets RFC 9110.ByteRange— une plage d’octets inclusive satisfaisable sur une représentation.FirstPageProber— la preuve structurelle « première page avant téléchargement complet ».
Types d’exception sous NextPDF\Pro\Webview\Exception :
WebviewException(interface marqueur),UnsupportedDocumentException,RangeNotSatisfiableException.
LinearizedDocument
Section intitulée « LinearizedDocument »Une classe final readonly à constructeur privé ; instancie-la via le constructeur nommé.
static fromBytes(string $bytes): self— analyse les octets via laLinearizationView::fromPdf()côté lecture du Core. LèveUnsupportedDocumentExceptionlorsque le document n’est pas linéarisé, lorsque la longueur/Ldéclarée ne correspond pas à la longueur réelle en octets, ou lorsque l’offset de fin de première page/En’est pas un offset positif à l’intérieur du fichier.length(): int— la longueur du document en octets.firstPagePrefixLength(): int— le préfixe de tête minimal qui contient la première page complète : l’offset/E, borné à la longueur du fichier.firstPageByteRange(): ByteRange— la plage inclusive[0, /E - 1]qui livre la première page. LèveRangeNotSatisfiableExceptionuniquement si le préfixe est vide (défense en profondeur ;fromBytes()garantit déjà0 < /E <= length).slice(int $firstByte, int $lastByte): string— découpe programmatique stricte avec offsets inclusifs ; lèveRangeNotSatisfiableExceptionen cas de dépassement de bornes.etag(): string— l’étiquette d’entité SHA-256 forte et déterministe pour les octets, mémoïsée une fois à la construction.
Propriétés publiques en lecture seule : bytes (les octets bruts du PDF) et view (la LinearizationView du Core).
ByteRangeResponder
Section intitulée « ByteRangeResponder »Une classe final readonly implémentée uniquement contre PSR-7 / PSR-17.
__construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf')— lèveInvalidArgumentExceptionlorsque$contentTypecontient des caractères de contrôle (il est interpolé dans les en-têtes de réponse et de partie multipart ; CR/LF et autres octets de contrôle sont rejetés pour prévenir l’injection d’en-tête).respond(LinearizedDocument $document, ServerRequestInterface $request): ResponseInterface— répond à une requête de plage pour un document linéarisé, en utilisant l’ETagpropre au document.respondToBytes(string $bytes, ServerRequestInterface $request, ?string $etag = null): ResponseInterface— répond à une requête de plage pour des octets arbitraires (une représentation qui devrait prendre en charge les plages sans être linéarisée). L’ETagest dérivé des octets lorsqu’il estnull.firstPageResponse(LinearizedDocument $document): ResponseInterface— construit un206portant exactement la plage d’octets de la première page ; la forme par poussée serveur de « première page avant téléchargement complet ».
ByteRange
Section intitulée « ByteRange »Un objet valeur final readonly pour une plage d’octets inclusive satisfaisable unique (RFC 9110 §14.1.2).
__construct(int $firstByte, int $lastByte, int $contentLength)— impose la satisfaisabilité0 <= firstByte <= lastByte <= contentLength - 1; lèveRangeNotSatisfiableExceptionsinon.length(): int— l’étendue inclusive (lastByte - firstByte + 1), toujours>= 1.contentRange(): string— la valeur du champContent-RangeRFC 9110 §14.4bytes first-last/length.
Propriétés publiques en lecture seule : firstByte, lastByte, contentLength.
FirstPageProber
Section intitulée « FirstPageProber »Une classe final readonly construite à partir d’un LinearizedDocument.
prefixLength(): int— nombre d’octets de tête minimal nécessaire pour afficher la première page.prefixFraction(): float— fraction du fichier entier (0.0–1.0) que le préfixe représente ; renvoie1.0pour un fichier de longueur nulle.hintStreamWithinPrefix(): bool— si l’objet de flux d’indices primaire se trouve entièrement à l’intérieur du préfixe de première page (de sorte que le préfixe seul permette à un lecteur de localiser les objets de la page 1). Le flux d’indices doit avoir une longueur positive.isFirstPageSelfContained(): bool— la preuve structurelle combinée : un préfixe positif qui tient dans le fichier et contient entièrement le flux d’indices.
Modèle requête/réponse par plage d’octets
Section intitulée « Modèle requête/réponse par plage d’octets »ByteRangeResponder suit RFC 9110 §14. Après avoir calculé la longueur et un ETag SHA-256 fort, il lit les en-têtes Range et If-Range et décide :
| Condition | Statut | Notes |
|---|---|---|
Aucun Range applicable, ou If-Range ne correspond pas à l’ETag fort courant | 200 OK | Corps complet. Seule la forme d’étiquette d’entité forte de If-Range est honorée (RFC 9110 §13.1.5). |
Unité de plage non reconnue ou Range syntaxiquement invalide | 200 OK | L’en-tête est ignoré (RFC 9110 §14.2). |
| Une plage satisfaisable | 206 Partial Content | Porte Content-Range. |
| Plusieurs plages satisfaisables | 206 Partial Content | multipart/byteranges avec une frontière dérivée. |
| Plages d’octets valides, aucune satisfaisable | 416 Range Not Satisfiable | Porte Content-Range: bytes */length (RFC 9110 §15.3.7). |
Chaque réponse annonce Accept-Ranges: bytes et l’ETag fort. Les réponses 200 et 206 définissent aussi Content-Type et Content-Length.
L’analyse de plage n’accepte que l’unité bytes=. Elle prend en charge les first-last explicites, les first- ouverts (bornés à la fin) et le suffixe -N (les N derniers octets ; un suffixe au moins aussi grand que la représentation la sélectionne en entier). Un - seul (ou toute autre spec mal formée) rend l’en-tête Range entier syntaxiquement invalide, si bien que l’en-tête est ignoré et que la représentation complète 200 OK est renvoyée. Un suffixe -0, ou toute spec dont le premier offset est au niveau ou au-delà de la fin, est une spec insatisfaisable et est écartée ; si aucune spec de l’en-tête n’est satisfaisable, la réponse est 416 Range Not Satisfiable. Les grands offsets décimaux sont comparés sans s’appuyer sur la saturation par dépassement d’entier, de sorte qu’une valeur Range de 30 chiffres soit gérée indépendamment de la plateforme. Les plages satisfaisables chevauchantes sont fusionnées avant la construction de tout corps ; les plages véritablement distinctes (non chevauchantes) sont préservées en parties multipart séparées.
Modes de défaillance et modèle d’exception
Section intitulée « Modes de défaillance et modèle d’exception »WebviewException est une interface marqueur qui étend Throwable ; capture-la pour gérer tout le sous-système de façon uniforme. Les deux exceptions concrètes l’implémentent.
UnsupportedDocumentException(étendInvalidArgumentException) — levée parLinearizedDocument::fromBytes()lorsque les octets ne sont pas un document linéarisé exploitable. Constructeurs nommés :notLinearized()(aucun dictionnaire de paramètres/Linearized),lengthMismatch($declaredLength, $actualLength)(le/Ldéclaré ne correspond pas à la longueur réelle — tronqué, augmenté par une mise à jour incrémentale au-delà de/L, ou non conforme), etmalformedFirstPageOffset($firstPageEndOffset, $length)(l’offset/En’est pas un offset positif à l’intérieur du fichier).RangeNotSatisfiableException(étendOutOfRangeException) — l’erreur de découpe programmatique, levée parByteRange::__construct()etLinearizedDocument::slice()/firstPageByteRange()lorsqu’une plage inclusive tombe en dehors du document. Constructeur nommé :outOfBounds($firstByte, $lastByte, $length).
Le responder HTTP ne lève pas RangeNotSatisfiableException pour les en-têtes Range du client — une plage HTTP insatisfaisable est une réponse 416 (RFC 9110 §15.3.7), pas une exception. Cette exception est réservée au découpage programmatique direct, où une requête hors bornes est une erreur de l’appelant. ByteRangeResponder::__construct() lève une InvalidArgumentException simple (pas une WebviewException) lorsque le contentType configuré contient des caractères de contrôle.
Durcissement contre le déni de service
Section intitulée « Durcissement contre le déni de service »Le responder plafonne le nombre de plages fusionnées distinctes honorées par requête (la classe d’amplification de plage multipart, Apache HTTPD CVE-2011-3192). Lorsqu’une requête demande plus de plages fusionnées que le plafond, ou plus d’octets au total que la représentation entière, le Range est ignoré et un 200 complet est renvoyé. La frontière multipart est dérivée de façon déterministe et re-dérivée jusqu’à ce que son occurrence à l’intérieur du corps soit garantie impossible, préservant une sortie reproductible tout en excluant la collision de frontière.
Conformité
Section intitulée « Conformité »Le comportement par plage d’octets suit RFC 9110 (HTTP Semantics) : §14 (requêtes de plage), §13.1.5 (If-Range), §14.4 (Content-Range) et §15.3.7 (416). L’agencement de document linéarisé est le modèle Fast Web View d’ISO 32000-2 Annex F. Le module n’affirme aucun autre identifiant de clause externe au-delà du comportement vérifié par ses tests.
Cas limites et comportement en mode FIPS
Section intitulée « Cas limites et comportement en mode FIPS »respondToBytes()sert des plages sur des octets arbitraires lorsque la sémantique de première page n’est pas nécessaire.- Un validateur
If-Rangeà date HTTP est traité comme une non-correspondance →200complet (le client se contente de re-récupérer). - L’
ETagest un hachage SHA-256 utilisé purement comme validateur de cache fort ; ce module n’effectue aucune signature ni autre opération cryptographique et ne définit aucun comportement spécifique à FIPS.
Périmètre de publication
Section intitulée « Périmètre de publication »Cette page documente uniquement le comportement observable de l’extérieur et la surface d’API publique prise en charge. Les chemins de namespace internes, les classes utilitaires, les tables de mécanismes, les noms de fichiers de runbook et les préfixes de tickets sont hors périmètre.