Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Openapi Psr7 Validator Laravel Package

league/openapi-psr7-validator

Validate PSR-7 HTTP requests and responses against OpenAPI 3.0.x specifications written in YAML or JSON. Matches requests to operations and checks bodies, headers, and metadata.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What this package is (TPM summary). league/openapi-psr7-validator is a spec-driven contract enforcement library. It takes an OpenAPI 3.0.x document (YAML/JSON) plus a PSR-7 HTTP message and answers one question: does this request/response actually conform to the published contract? That makes it a governance and quality lever rather than a feature library — its business value is in catching contract drift, not in shipping endpoints.

Architecture fit. Strong fit for any PSR-compliant HTTP stack. The library is deliberately framework-agnostic: it operates on ServerRequestInterface/ResponseInterface, ships a PSR-15 middleware, a Slim adapter, and a standalone schema validator. It is a library, not a runtime — no daemons, no network hops, no external service. That means it slots into three distinct places in our estate: CI (contract tests), staging middleware (drift detection), and production middleware (guardrails on public APIs). This is a rare package that is useful at all three tiers with the same artifact.

Integration feasibility. Low for CI, moderate for Laravel runtime. composer require league/openapi-psr7-validator is the whole install. Three integration surfaces matter to us:

  1. Test-time validation — validate request/response objects inside PHPUnit feature tests. Highest value, lowest risk, near-zero production blast radius.
  2. PSR-15 middleware — a drop-in middleware wrapping the request pipeline. Native for Slim; requires plumbing on Laravel (no native PSR-15 middleware pipeline) and Symfony (HttpKernel is not PSR-15).
  3. Standalone SchemaValidator — validate arbitrary domain payloads against an OAS schema fragment. Useful for consumers, webhook payloads, and internal service boundaries where we do not have a full spec-driven HTTP layer.

The RoutedRequestValidator is the performance-conscious option and the correct default where we already know the route (which we do in Laravel). It avoids the library's path-matching pass entirely.

Technical risk. Ranked:

  • OpenAPI 3.0.x only. No 3.1 support visible in the README. If our API design guild is standardizing on 3.1 (JSON Schema 2020-12 alignment), this package becomes a legacy-surface tool only. This is the single biggest strategic risk and must be answered before we anchor our contract-testing strategy on it.
  • cebe/openapi dependency. The spec object model comes from a third-party package; its maintenance cadence and 3.1 support directly bound what we can do. Two transitive OSS dependencies for one capability.
  • Exception taxonomy is rich but not HTTP-shaped. The package throws InvalidBody, InvalidQueryArgs, InvalidCookies, InvalidPath, NoContentType, NoOperation, MultipleOperationsMismatchForRequest, etc. These are excellent for observability and test assertions, but we own the mapping to our error envelope (RFC 7807 or equivalent). Do not assume a failed validation returns a clean 400 — that is our code to write.
  • Spec quality is the real failure mode. An incomplete spec turns a correct request into a false rejection. The library faithfully enforces whatever we wrote, including our mistakes. Runtime enforcement is only as safe as spec coverage.
  • Bus factor / adoption signal. 563 stars, 0 tracked dependents, single-primary-author history. It is a healthy League package, but not a high-velocity one. Treat it as "stable and quiet," and pin the version.

Key questions for the team before adoption.

  1. Which OAS version do our published specs use today, and is 3.1 on the roadmap? If 3.1 is imminent, scope this to 3.0 surfaces only.
  2. Is our source-of-truth spec generated from code, or hand-authored? Hand-authored specs will produce false positives at runtime and must be gated to CI first.
  3. Where do we want enforcement: CI, staging, production, or all three — and what is the default action on violation (log, reject, alert)?
  4. Who owns the spec → validator → cache invalidation loop when a spec deploy lands?
  5. Do we need custom formats (domain-specific identifiers, currency codes)? The FormatsContainer::registerFormat hook makes this cheap, but registration is global process state and needs a single bootstrap location.

Integration Approach

Stack fit. Laravel is the primary target and the friction is entirely in the PSR boundary: Laravel speaks Illuminate\Http\Request, this library speaks PSR-7. We bridge with symfony/psr-http-message-bridge + a PSR-7 implementation (nyholm/psr7 or guzzlehttp/psr7). That bridge is the only meaningful new dependency. For response validation, we additionally need to convert Illuminate\Http\Response back to a PSR-7 response — doable, but it is the point where I would question runtime response validation in production versus asserting it in tests instead.

Slim and other PSR-native stacks get this for free. Symfony and Lumen need a shim; Symfony in practice is better served by doing validation at the test layer.

Recommended primary pattern: CI contract tests. Wrap the application's HTTP tests so that every feature test asserts both the happy path and spec conformance of the request and the response. This delivers the majority of the governance value with none of the runtime risk, and it is where I would spend the first two sprints.

Secondary pattern: staging middleware in observe-only mode. Install the PSR-15 middleware in staging, catch every ValidationFailed subtype, log structured events (operation, exception class, keyword, data breadcrumb), and never reject. Run for 2–3 weeks. The resulting log is the actual deliverable: it tells us exactly which spec gaps and client behaviors exist before we consider enforcement. This is the highest-signal, lowest-risk phase of the rollout.

Tertiary pattern: selective production enforcement. Only after staging logs are clean for a defined surface. Start with request validation on a small set of endpoints (webhooks, partner APIs, public write endpoints) where a 400 on malformed input is genuinely desirable. Never enable response validation in production on high-traffic paths — it doubles serialization cost and a spec bug there is an outage.

Compatibility and migration path.

  • The package has no migration surface of its own: adopting it does not require changing controllers, routing, or serialization. It is additive.
  • Migration is spec migration, not code migration. The 3.0.x ceiling means any 3.1-only constructs (e.g. null type unions in the way 3.1 expresses them) must stay out of specs we intend to validate.
  • Version pin with composer.json constraint and a lock file; monitor releases manually since dependents are near zero and automated ecosystem signals will be thin.

Sequencing (five phases, each independently valuable):

  1. Spec inventory and lint. Catalogue every service's OAS document, version, and completeness. Nothing else proceeds until we know what we would be validating against.
  2. CI enforcement. Add request/response conformance assertions to the test suite of one pilot service. Instrument the failure rate. This is the go/no-go gate for the whole initiative.
  3. Custom formats and exception mapping. Register domain formats in a single bootstrap; build a shared exception → error-envelope mapper (one class, reused everywhere).
  4. Staging observe mode with caching. Enable the PSR-15 middleware, wire ->setCache($pool, $ttl) against APCu or Redis with ->overrideCacheKey() keyed on spec version. This is where we learn real-world cost.
  5. Selective production enforcement. Gate on a per-endpoint allowlist, feature-flagged, with a documented rollback (flip to observe).

Performance notes to bake in from day one. Use getRoutedRequestValidator() wherever the route is already resolved — the unmatched-path fallback is the expensive branch. Enable the PSR-6 cache layer unconditionally outside tests; without it we re-parse and recompile the spec on every request, which is unacceptable at any real QPS. Cache key must incorporate the spec version so a deploy cannot serve stale validation.

Operational Impact

Maintenance burden. Low code maintenance, non-trivial contract maintenance. The library itself is quiet — MIT licensed, stable API, single dependency chain. The recurring cost is keeping specs accurate, which is a documentation discipline the package makes visible but does not solve. Budget for a named owner of the spec lifecycle; without one, this degrades into noisy false positives within a quarter.

Support and vendor posture. Community-supported OSS with no SLA. There is no commercial backing to escalate to. Mitigations: pin the version, keep an internal fork-readiness note (the package is small enough to patch), and avoid it on any path where a validation bug is a revenue event.

Scaling characteristics. Validation cost is dominated by spec parsing/compilation, then per-message schema evaluation. Both are addressable: the PSR-6 cache eliminates recompilation, and the routed validator eliminates path matching. Residual per-request cost is proportional to payload size and schema complexity — non-trivial for large bodies with deep oneOf/anyOf compositions. Do not enable response validation on high-volume read paths. Do not validate on health checks or static asset routes. Expect the middleware to be a low single-digit percentage of request latency once cached; that is acceptable for guardrails but not for every endpoint on every request.

Failure modes to design for.

  • False rejection on a valid request — caused by an incomplete or stale spec. Highest-severity mode; mitigated by observe-first rollout and a kill switch. This is why production enforcement is a per-endpoint decision, not a blanket policy.
  • Spec cache staleness after deploy — new endpoints 404 against the old cached spec. Mitigated by version-keyed cache keys and cache flush on release.
  • Missing Content-Type — NoContentType is thrown before any schema work; clients with sloppy headers will trip this. Treat as a separate triage bucket from genuine schema violations, or it will swamp the signal.
  • Ambiguous operations — MultipleOperationsMismatchForRequest when several operations match a request. Almost always a spec design problem (overlapping paths); fix the spec, do not suppress the exception.
  • Exception-to-HTTP mapping bugs — our mapper, our bug. Any uncaught validation exception becomes a 500 rather than a 400. This needs explicit test coverage in the mapper.
  • Global mutable state — custom formats are registered process-wide via FormatsContainer::registerFormat. Register once in a bootstrap; duplicate or conditional registration in request scope is a latent bug.

Ramp-up. A competent Laravel engineer is productive in under a day for the test-time pattern: the builder API is fluent and self-evident from the README. The PSR-7 bridging and the exception taxonomy are where the learning lives — roughly two to three days to be confident writing the exception mapper and the middleware wiring. The library ships no production examples for Laravel specifically, so plan for an internal reference implementation (one service, one middleware, one mapper) that others copy. Slim users ramp faster.

Operational KPIs I would track. Validation failure rate by exception class (separating spec defects from client defects from mapping bugs), percentage of published endpoints with conformance coverage, staging observe-mode false-positive rate before any enforcement decision, and p95 added latency attributable to the middleware once cached. Those four numbers are the entire business case for continuing or killing the rollout.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib