Aller au contenu

Inspect : introspection et contrôle en amont des PDF

Le module Inspect analyse un PDF existant et décrit son contenu : score de complexité, audits des polices et des images, indices de conformité et indicateurs de risque. Une politique de contrôle en amont transforme ce rapport en verdict pass/fail, ce qui te permet de filtrer un document avant son entrée dans un pipeline.

Stabilité : expérimentale. L’introspection est une surface en évolution. La forme de InspectResult, l’ensemble des indicateurs de risque et le chemin d’inspection accéléré optionnel peuvent changer d’une version mineure à l’autre. Utilise-le pour le diagnostic et le filtrage ; ne fige pas encore de contrats pérennes sur la forme de son résultat.

Fenêtre de terminal
composer require nextpdf/core:^3

Inspector est le point d’entrée. Il implémente InspectorInterface et expose une seule méthode : inspect(string $pdfData, InspectConfig $config = new InspectConfig()): InspectResult. Il fonctionne en lecture seule — il analyse un PDF et le caractérise ; il ne modifie pas le document.

InspectResult est le rapport structuré. Il regroupe le score de complexité, les audits, les indices et un ensemble de RiskFlag. Il répond à hasRisks() / hasRisk(RiskFlag $flag), ce qui permet à l’appelant de se brancher sur un risque précis au lieu d’analyser du texte libre. ComplexityScore expose un score numérique ainsi qu’une plage category(). FontAuditEntry et ImageAuditEntry décrivent les ressources intégrées. ComplianceHint signale les problèmes de conformité probables. InspectIssue consigne une constatation précise. InspectDepth choisit la profondeur de l’inspection, et toSpectrumDepth() l’associe au chemin accéléré lorsque le sidecar Spectrum est disponible. L’inspection fonctionne sans le sidecar. Le sidecar ne change que les performances, pas le contrat. InspectResponseParser construit un InspectResult à partir d’une réponse brute (par exemple celle du chemin accéléré) avec un identifiant de trace optionnel.

PreflightPolicy est la couche de décision. evaluate(InspectResult $result) applique une politique configurée à un résultat et renvoie le verdict de cette politique. L’ensemble du module est @since 2.2.0.

TypeMembres clésRôle
Inspectorinspect(string $pdfData, InspectConfig $config): InspectResultInspecteur de PDF en lecture seule (@since 2.2.0)
InspectResulthasRisks(), hasRisk(RiskFlag), accesseurs score/auditRapport d’inspection structuré (@since 2.2.0)
ComplexityScorecategory()Score de complexité numérique + plage (@since 2.2.0)
FontAuditEntry / ImageAuditEntryaccesseurs de ressourcesAudits de ressources intégrées (@since 2.2.0)
ComplianceHint / InspectIssueaccesseurs de constatationsIndices de conformité et constatations (@since 2.2.0)
InspectDepth (énumération)toSpectrumDepth()Profondeur d’inspection → chemin accéléré (@since 2.2.0)
PreflightPolicyevaluate(InspectResult): array, toArray()Décision de contrôle en amont pass/fail (@since 2.2.0)
InspectResponseParserparse(array, InspectConfig, ?string $traceId): InspectResultConstruit un résultat à partir d’une réponse brute (@since 2.2.0)

Exécute composer docs:generate-api-php -- --module=Inspect pour obtenir la table PHPDoc complète.

Source : examples/34-inspect-layout-boxes.php montre comment lire la géométrie des pages. Pour inspecter le profil de risque d’un PDF arbitraire :

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Inspect\Inspector;
$result = (new Inspector())->inspect(file_get_contents('/srv/in/incoming.pdf'));
if ($result->hasRisks()) {
echo "Complexity: {$result->complexityScore()->category()}; risks present.\n";
}

Filtre un PDF entrant avec une politique de contrôle en amont et rejette-le au moindre risque.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Inspect\Inspector;
use NextPDF\Inspect\PreflightPolicy;
use Psr\Log\LoggerInterface;
final readonly class IngestPreflight
{
public function __construct(
private Inspector $inspector,
private PreflightPolicy $policy,
private LoggerInterface $logger,
) {}
public function accept(string $pdfData): bool
{
$result = $this->inspector->inspect($pdfData);
$verdict = $this->policy->evaluate($result);
if ($verdict !== []) {
$this->logger->warning('PDF rejected at preflight.', ['findings' => $verdict]);
return false;
}
return true;
}
}
  • inspect() est en lecture seule. Il ne modifie ni ne répare jamais l’entrée ; ne t’attends pas à récupérer un document « corrigé ».
  • hasRisk(RiskFlag) sert à vérifier un risque précis. Te baser uniquement sur hasRisks() traite chaque risque de façon identique — en général, tu veux un indicateur précis.
  • InspectDepth contrôle le coût. Une inspection en profondeur d’un PDF volumineux est nettement plus lente ; choisis la profondeur la plus faible qui réponde à ta question.
  • Le chemin accéléré par Spectrum change les performances, pas le contrat du résultat. Code en t’appuyant sur InspectResult, pas sur la structure de la réponse accélérée.
  • PreflightPolicy::evaluate() renvoie les constatations ; il ne lève pas d’exception. Un résultat vide est un succès — agis en fonction de la valeur de retour.

Le coût de l’inspection augmente avec la taille du document et l’InspectDepth choisi. Une inspection superficielle est rapide ; un audit en profondeur d’un PDF volumineux peut approcher le budget. Le chemin Spectrum décharge l’analyse lourde lorsqu’il est disponible. Le performance_budget de 1500 ms en temps écoulé / 64 Mo en pic correspond à la charge de travail de référence. Le profil de reproductibilité est structural : un résultat peut porter un identifiant de trace et un chronométrage. Deux exécutions diffèrent sur ces champs, tandis que les constatations restent stables pour une même entrée.

Inspector::inspect() analyse des octets PDF non fiables — c’est précisément son rôle, donc traite l’entrée comme hostile. Exécute l’inspection dans un worker restreint pour les documents fournis par l’utilisateur et limite en amont la taille de l’entrée. Un PDF délibérément complexe est un vecteur de déni de service, quelle que soit la profondeur. Le résultat décrit le document, mais ne l’assainit pas — un verdict « risque faible » est une heuristique, pas une garantie de sûreté. Traite les chaînes et les métadonnées extraites comme non fiables. Consulte le modèle de menaces du moteur dans /modules/core/security/.

Ce module rend compte d’indices de conformité ; il ne constitue pas le verdict de conformité faisant autorité. ComplianceHint signale les problèmes probables de façon heuristique. Le verdict de conformité PDF/A, PDF/UA et ISO 32000-2 faisant autorité provient des validateurs de référence pilotés par /modules/core/cli/ ainsi que des suites d’oracle et de référence décrites dans /modules/core/conformance/. Ne considère pas un résultat Inspect sans constatation comme une certification de conformité.