Pro edição
Webview — Referência Profunda
Visão geral
Seção intitulada “Visão geral”Esta página documenta a superfície pública NextPDF\Pro\Webview, o modelo de requisição/resposta por intervalo de bytes e os exatos modos de falha além da página pública de apresentação.
Disponibilidade e licenciamento
Seção intitulada “Disponibilidade e licenciamento”Esta capacidade é distribuída no NextPDF Pro (nextpdf/pro) e é ativada com um envelope de licença de nível Pro. Uma implantação sem essa titularidade não carrega as classes da capacidade. Compare as edições e obtenha uma licença.
Não há sinalizador de licença por recurso; o código é distribuído com a edição Pro. O ResponseFactoryInterface / StreamFactoryInterface PSR-17 e o media type do corpo são parâmetros de runtime do construtor, não controles de licenciamento.
Superfície da API pública
Seção intitulada “Superfície da API pública”composer require nextpdf/proTipos públicos sob NextPDF\Pro\Webview:
LinearizedDocument— um PDF linearizado validado e preparado para a entrega.ByteRangeResponder— o responder HTTP por intervalo de bytes do RFC 9110.ByteRange— um intervalo de bytes inclusivo satisfazível sobre uma representação.FirstPageProber— a prova estrutural de “primeira página antes do download completo”.
Tipos de exceção sob NextPDF\Pro\Webview\Exception:
WebviewException(interface marcadora),UnsupportedDocumentException,RangeNotSatisfiableException.
LinearizedDocument
Seção intitulada “LinearizedDocument”Uma classe final readonly com um construtor privado; instancie via o construtor nomeado.
static fromBytes(string $bytes): self— analisa os bytes por meio daLinearizationView::fromPdf()do lado de leitura do Core. LançaUnsupportedDocumentExceptionquando o documento não é linearizado, quando o/Ldeclarado não corresponde ao comprimento real em bytes, ou quando o offset/Ede fim da primeira página não é um offset positivo dentro do arquivo.length(): int— o comprimento do documento em bytes.firstPagePrefixLength(): int— o prefixo inicial mínimo que contém a primeira página completa: o offset/E, fixado ao comprimento do arquivo.firstPageByteRange(): ByteRange— o intervalo inclusivo[0, /E - 1]que entrega a primeira página. LançaRangeNotSatisfiableExceptionapenas se o prefixo for vazio (defesa em profundidade;fromBytes()já garante0 < /E <= length).slice(int $firstByte, int $lastByte): string— fatia programática estrita com offsets inclusivos; lançaRangeNotSatisfiableExceptionquando fora dos limites.etag(): string— a entity-tag SHA-256 forte e determinística para os bytes, memoizada uma única vez na construção.
Propriedades públicas readonly: bytes (os bytes brutos do PDF) e view (a LinearizationView do Core).
ByteRangeResponder
Seção intitulada “ByteRangeResponder”Uma classe final readonly implementada apenas contra PSR-7 / PSR-17.
__construct(ResponseFactoryInterface $responses, StreamFactoryInterface $streams, string $contentType = 'application/pdf')— lançaInvalidArgumentExceptionquando$contentTypecontém caracteres de controle (ele é interpolado nos cabeçalhos da resposta e das partes multipart; CR/LF e outros bytes de controle são rejeitados para evitar injeção de cabeçalho).respond(LinearizedDocument $document, ServerRequestInterface $request): ResponseInterface— responde a uma requisição de intervalo para um documento linearizado, usando o próprioETagdo documento.respondToBytes(string $bytes, ServerRequestInterface $request, ?string $etag = null): ResponseInterface— responde a uma requisição de intervalo para bytes arbitrários (uma representação que deve suportar intervalos sem ser linearizada). OETagé derivado dos bytes quandonull.firstPageResponse(LinearizedDocument $document): ResponseInterface— constrói um206carregando exatamente o intervalo de bytes da primeira página; a forma de server-push de “primeira página antes do download completo”.
ByteRange
Seção intitulada “ByteRange”Um value object final readonly para um único intervalo de bytes inclusivo satisfazível (RFC 9110 §14.1.2).
__construct(int $firstByte, int $lastByte, int $contentLength)— impõe a satisfazibilidade0 <= firstByte <= lastByte <= contentLength - 1; lançaRangeNotSatisfiableExceptioncaso contrário.length(): int— o intervalo inclusivo (lastByte - firstByte + 1), sempre>= 1.contentRange(): string— o valor do campoContent-Rangedo RFC 9110 §14.4bytes first-last/length.
Propriedades públicas readonly: firstByte, lastByte, contentLength.
FirstPageProber
Seção intitulada “FirstPageProber”Uma classe final readonly construída a partir de um LinearizedDocument.
prefixLength(): int— a contagem mínima de bytes iniciais necessária para renderizar a primeira página.prefixFraction(): float— a fração de todo o arquivo (0.0–1.0) que o prefixo representa; retorna1.0para um arquivo de comprimento zero.hintStreamWithinPrefix(): bool— se o objeto de stream de hint primário está totalmente dentro do prefixo da primeira página (de modo que apenas o prefixo permita a um leitor localizar os objetos da página 1). O stream de hint deve ter comprimento positivo.isFirstPageSelfContained(): bool— a prova estrutural combinada: um prefixo positivo que cabe dentro do arquivo e contém totalmente o stream de hint.
Modelo de requisição/resposta por intervalo de bytes
Seção intitulada “Modelo de requisição/resposta por intervalo de bytes”ByteRangeResponder segue o RFC 9110 §14. Após calcular o comprimento e um ETag SHA-256 forte, ele lê os cabeçalhos Range e If-Range e decide:
| Condição | Status | Notas |
|---|---|---|
Sem Range aplicável, ou If-Range não corresponde ao ETag forte atual | 200 OK | Corpo completo. Apenas a forma de entity-tag forte de If-Range é honrada (RFC 9110 §13.1.5). |
Unidade de intervalo não reconhecida ou Range sintaticamente inválido | 200 OK | O cabeçalho é ignorado (RFC 9110 §14.2). |
| Um intervalo satisfazível | 206 Partial Content | Carrega Content-Range. |
| Vários intervalos satisfazíveis | 206 Partial Content | multipart/byteranges com um boundary derivado. |
| Intervalos de bytes válidos, nenhum satisfazível | 416 Range Not Satisfiable | Carrega Content-Range: bytes */length (RFC 9110 §15.3.7). |
Toda resposta anuncia Accept-Ranges: bytes e o ETag forte. As respostas 200 e 206 também definem Content-Type e Content-Length.
A análise de intervalo aceita apenas a unidade bytes=. Ela suporta first-last explícito, first- em aberto (fixado ao fim) e sufixo -N (os últimos N bytes; um sufixo pelo menos tão grande quanto a representação seleciona-a por inteiro). Um - isolado (ou qualquer outra spec malformada) torna todo o cabeçalho Range sintaticamente inválido, de modo que o cabeçalho é ignorado e a representação 200 OK completa é retornada. Um sufixo -0, ou qualquer spec cujo primeiro offset esteja no fim ou além dele, é uma spec insatisfazível e é descartada; se nenhuma spec do cabeçalho for satisfazível, a resposta é 416 Range Not Satisfiable. Offsets decimais grandes são comparados sem depender da saturação por estouro de inteiro (integer-overflow), de modo que um valor Range de 30 dígitos é tratado de forma independente de plataforma. Intervalos satisfazíveis sobrepostos são coalescidos antes que qualquer corpo seja construído; intervalos genuinamente distintos (não sobrepostos) são preservados como partes multipart separadas.
Modos de falha e modelo de exceções
Seção intitulada “Modos de falha e modelo de exceções”WebviewException é uma interface marcadora que estende Throwable; capture-a para tratar todo o subsistema de maneira uniforme. Ambas as exceções concretas a implementam.
UnsupportedDocumentException(estendeInvalidArgumentException) — levantada porLinearizedDocument::fromBytes()quando os bytes não são um documento linearizado utilizável. Construtores nomeados:notLinearized()(sem dicionário de parâmetros/Linearized),lengthMismatch($declaredLength, $actualLength)(o/Ldeclarado não corresponde ao comprimento real — truncado, com anexos via uma atualização incremental além de/L, ou não conforme) emalformedFirstPageOffset($firstPageEndOffset, $length)(o offset/Enão é um offset positivo dentro do arquivo).RangeNotSatisfiableException(estendeOutOfRangeException) — o erro de fatiamento programático, levantado porByteRange::__construct()eLinearizedDocument::slice()/firstPageByteRange()quando um intervalo inclusivo cai fora do documento. Construtor nomeado:outOfBounds($firstByte, $lastByte, $length).
O responder HTTP não lança RangeNotSatisfiableException para cabeçalhos Range do cliente — um intervalo HTTP insatisfazível é uma resposta 416 (RFC 9110 §15.3.7), não uma exceção. Essa exceção é reservada para o fatiamento programático direto, em que uma requisição fora dos limites é um erro do chamador. ByteRangeResponder::__construct() lança uma InvalidArgumentException simples (não uma WebviewException) quando o contentType configurado contém caracteres de controle.
Endurecimento contra negação de serviço
Seção intitulada “Endurecimento contra negação de serviço”O responder limita o número de intervalos coalescidos distintos honrados por requisição (a classe de amplificação de intervalo multipart, Apache HTTPD CVE-2011-3192). Quando uma requisição pede mais intervalos coalescidos do que o limite, ou mais bytes totais do que toda a representação, o Range é ignorado e um 200 completo é retornado. O boundary de multipart é derivado de forma determinística e re-derivado até ter a garantia de não ocorrer dentro do corpo, preservando a saída reproduzível ao mesmo tempo em que descarta a colisão de boundary.
Conformidade
Seção intitulada “Conformidade”O comportamento por intervalo de bytes segue o RFC 9110 (HTTP Semantics): §14 (requisições de intervalo), §13.1.5 (If-Range), §14.4 (Content-Range) e §15.3.7 (416). O layout de documento linearizado é o modelo Fast Web View do ISO 32000-2 Annex F. O módulo não afirma nenhum identificador de cláusula externo além do comportamento verificado por seus testes.
Casos extremos & comportamento em modo FIPS
Seção intitulada “Casos extremos & comportamento em modo FIPS”respondToBytes()serve intervalos sobre bytes arbitrários quando a semântica de primeira página não é necessária.- Um validador
If-Rangede data HTTP é tratado como não correspondente →200completo (o cliente simplesmente busca novamente). - O
ETagé um hash SHA-256 usado puramente como um validador de cache forte; este módulo não realiza nenhuma assinatura ou outra operação criptográfica e não define nenhum comportamento específico de FIPS.
Limite de publicação
Seção intitulada “Limite de publicação”Esta página documenta apenas o comportamento observável externamente e a superfície pública da API suportada. Caminhos de namespace internos, classes auxiliares, tabelas de mecanismos, nomes de arquivos de runbook e prefixos de tíquete estão fora do escopo.