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

Json Rpc Bundle Laravel Package

nanofelis/json-rpc-bundle

Symfony bundle for building JSON-RPC 2.0 APIs. Expose services as RPC methods, handle requests and errors consistently, and integrate JSON-RPC endpoints with Symfony routing and dependency injection.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — unchanged: poor as a direct dependency. 6.0.0 is still a Symfony bundle (NanofelisJsonRpcBundle). The integration surface remains the Bundle system — DI Extension, compiler passes, tagged services, service locators built at container-compile time, and Symfony routing/HttpKernel hooks. Laravel has no equivalent for the pieces this release leans into hardest. In fact 6.0.0 moves further into Symfony-specific machinery, not away from it.

Integration feasibility — still extraction-only, and the extractable core is now a smaller fraction of the package. The changes that make 6.0.0 good news for Symfony users are, almost without exception, wiring-layer changes that have no Laravel analogue and therefore no portability value:

  • Build-time resolution of service keys via a compiler pass and a service locator (fixes eager instantiation of every tagged service).
  • Duplicate #[JsonRpcService] key detection at container build time.
  • RPC methods routed through Symfony's controller argument lifecycle so #[MapRequestPayload] and custom argument resolvers work.
  • kernel.controller_arguments replacing the removed RpcBeforeMethodEvent / nanofelis_json_rpc.before_method listener.
  • #[JsonRpcService] autoconfiguration.

None of that transfers. What does remain portable is the JSON-RPC 2.0 semantics core — parsing, dispatch, batch assembly, error-code mapping — and this release is a strong signal that the semantics core is now materially better than it was at 5.x. The 1–2 day spike should be scoped accordingly: find the parser/dispatcher/error-mapper classes, confirm they don't type-hint HttpKernel or resolve handlers through the Symfony container, and ignore everything above them.

Technical risk — meaningfully changed, in two directions.

Improved:

  • Maintainer responsiveness is now demonstrated, not assumed. A published migration guide, a full changelog, a coordinated breaking release, and a security fix shipped together is the profile of an actively maintained project. This partially — not fully — retires the "no realistic expectation of a fix" concern from the previous assessment.
  • A real vulnerability was found and closed. 5.x exposed __construct on #[JsonRpcService] services, letting a caller re-invoke the constructor on the container-shared instance and overwrite injected dependencies for the remainder of the request — or the worker process under FrankenPHP/RoadRunner. That is a serious bug class, and the fix (an allowlist of public, non-magic, non-abstract methods; everything else answers -32601) is the correct one.
  • The spec edges we flagged as likely-wrong are the ones they fixed. Malformed batch entries no longer discard sibling calls; empty batch [] now answers -32600; non-conforming id (float, array) answers -32600 instead of a TypeError/500; a missing jsonrpc key no longer emits an undefined-key warning en route to -32600.
  • max_batch_size (default 100, 0 disables) addresses the batch-amplification hazard directly, which is the single hardest operational problem with this protocol shape.
  • Wider Symfony constraint range (6.4/7/8) modestly reduces Composer conflict risk against Laravel's pinned Symfony components.

Worsened or newly introduced:

  • PHP >= 8.4 is a hard floor and a new gating constraint. If the deployment target is 8.2 or 8.3, this package cannot be installed at all — the spike degrades to reading source and docs on GitHub rather than running the test suite. That is a cheaper spike, but a weaker one.
  • Dropped Symfony 5 and removed symfony/twig-bundle and ext-dom from transitive requirements — the latter is a silent breakage for anyone who was relying on them arriving for free. Irrelevant for a Laravel port, relevant if any adjacent tooling assumed them.
  • The prior metadata anomaly is unresolved. The 2026-08-20 release date noted previously cannot be reconciled from the data supplied here. The release notes are substantive and internally consistent, which raises confidence, but tag/commit/CI verification on the repository remains a precondition before any decision.
  • Baseline adoption signals are unchanged: ~11 stars, 0 dependents, single maintainer, no third-party production usage, no external security review beyond this one self-reported fix.

Key questions for the requester/team:

  1. Is JSON-RPC 2.0 a hard external contract, or an internal stylistic preference? Unchanged, and still blocks everything.
  2. What is our PHP floor, and are we on 8.4+? New question, and now the first one — it determines whether the package is even installable and therefore whether the spike is empirical or a code read.
  3. Which spec features are in scope: batch, notifications, named vs. positional params, custom error data, server and/or client direction?
  4. Do we accept indefinite ownership of a fork or vendored copy? Unchanged — and still disqualifying if the answer is no, regardless of the improved maintenance signal.
  5. Auth, per-method authorization, rate limiting, and request-size expectations per method — these determine whether any off-the-shelf dispatch layer fits or whether we need bespoke code anyway.
  6. Worker-mode deployment: are we on Octane/RoadRunner/FrankenPHP? The 6.0.0 vulnerability was specifically a worker-process state-bleed bug. If we run long-lived workers, our own implementation must be audited for the same class of problem.

Integration Approach

Stack fit — unchanged: mismatch at the wiring layer. The realistic target remains Laravel-native code: a service provider for handler bindings, a route, and middleware for auth/throttling/logging.

Migration path — preference order unchanged, but the rationale for option 1 strengthens.

  1. Build Laravel-native, borrow the design. Implement a thin controller + dispatcher using the container, validation, and middleware. This release makes the package a considerably better reference: it now encodes a considered position on batch splitting, empty batches, id validation, and method-surface allowlisting. Lowest long-term risk, full control of error semantics. Still the recommendation.
  2. Vendor the core classes. Still viable if the spike shows the parser/dispatcher are framework-agnostic. Note that 6.0.0's most valuable fixes are in the bundle wiring, not the core, so vendoring inherits less of the improvement than it first appears. We would still be writing the allowlist, the batch cap, and the id validation ourselves.
  3. Pull the full bundle. Still not recommended, and now harder — service locators and compiler passes deepen the Symfony dependency rather than shallow it.

Two things to lift from this release into our own build regardless of option:

  • The callable-method allowlist. Only public, non-magic, non-abstract methods should be invokable; everything else returns -32601. Do not expose constructors, __destruct, __call, or inherited framework methods. This is now a known bug class in this protocol's PHP implementations, not a theoretical one.
  • max_batch_size with a documented default. Adopt 100 (or lower) as a starting cap and make it configurable.

Compatibility checks required before committing:

  • PHP floor: 8.4. Verify against the deployment target before anything else.
  • composer why-not nanofelis/json-rpc-bundle against the target Laravel version — Symfony 6.4/7/8 range is broader than before, but Laravel's pinned symfony/* versions still govern.
  • Any reliance on symfony/twig-bundle or ext-dom arriving transitively — now explicitly removed.
  • Whether symfony/serializer or symfony/validator are pulled in; either expands the integration surface.

Sequencing.

  1. Confirm the protocol requirement and scope the spec features (blocks everything).
  2. Confirm the PHP floor can accommodate 8.4; if not, plan the spike as a source read.
  3. Timeboxed spike: isolate the parser/dispatcher/error-mapper; record what is extractable vs. Symfony-bound. Decision gate: build vs. vendor.
  4. Implement the dispatch core, handler registration in a service provider, and the method allowlist.
  5. Decide batch response ordering explicitly. 6.0.0 permits any order and tells clients to correlate on id. Preserving input order is strictly safer for interoperability; do that unless a client requires otherwise, and document the guarantee either way.
  6. Layer middleware: authentication, per-method authorization, rate limiting, structured request/response logging keyed on the JSON-RPC id.
  7. Build the contract test suite from the JSON-RPC 2.0 spec. Mine the 6.0.0 changelog and migration guide for the case list — malformed batch entry, empty batch, non-conforming id, missing jsonrpc key, method-not-found via disallowed surface. These are now known-tricky cases with known-correct answers.
  8. Load test batch endpoints specifically, with the cap enforced (see scaling below).
  9. Feature-flag rollout to one internal consumer before any external client.

Operational Impact

Maintenance. The ownership picture is unchanged in kind but improved in degree: the upstream project is demonstrably alive, ships migration documentation, and responds to security issues. That does not change the core fact — adopting it means owning a Symfony bundle inside a Laravel app — but it does make it a safer reference and a slightly less alarming thing to vendor from. Budget remains a small recurring allocation for spec conformance review on each new client onboarding. Note that 6.0.0 is a breaking release with a stated migration path; if we ever did vendor, we would now be tracking a moving target rather than a dead one, which is arguably better but is still work.

Support. No vendor, no SLA, no community of dependents. Escalation is "read the source." Unchanged. The security fix demonstrates the maintainer will act, but on no committed timeline, and we would have no advance notice of the next one.

Scaling. The batch-amplification hazard is now acknowledged upstream via max_batch_size — good validation that our concern was real, but the setting lives in bundle config and does not come with the core if we port it. We must implement the cap ourselves. Enforce a maximum batch size, apply rate limiting and authorization per method call rather than per HTTP request, and cap total batch execution time. Also confirm the response pipeline and any gateway in front of it handle a notification-only batch returning 204/empty correctly.

Failure modes to design for (updated).

  • Method-surface exposure — new top entry. A dispatcher that reflects over a service and invokes whatever it finds can expose constructors and magic methods. Allowlist explicitly; return -32601 for everything else.
  • Worker state bleed — relevant under Octane/RoadRunner/FrankenPHP. Handlers must not mutate shared service state per request; the 6.0.0 constructor-reinvocation bug is the canonical example of what goes wrong when they do.
  • Handler throws → must surface as a JSON-RPC error object, never a Laravel HTML exception page or a stack-traced 500.
  • Parse vs. invalid-request vs. method-not-found vs. invalid-params ambiguity → clients behave differently; get the codes right and test them.
  • Partial batch failure → some calls succeed, some fail; one malformed entry must not drop its siblings. Decide and document whether responses preserve input order (recommended) or correlate by id.
  • Empty batch [] → -32600, not an empty array.
  • Non-conforming id (float, array, object) → -32600, not a type error and not a 500.
  • Timeout mid-batch → indeterminate client-side state; document idempotency expectations per method.
  • Silent contract drift when an external client updates its interpretation of the spec.

Ramp-up. The protocol surface is still small and a PHP developer is productive in a day. Two additions: the 8.4 floor may mean the reference implementation cannot be run locally during the spike, so allow extra time for reading rather than experimenting; and the absence of a maintained library still means the on-call engineer debugging a malformed batch reads our code, not upstream docs. That is acceptable if chosen deliberately and documented — the new changelog makes that deliberate choice easier to justify, because it hands us a curated list of the mistakes to avoid.

Overall recommendation — unchanged. Do not adopt nanofelis/json-rpc-bundle as a dependency in a Laravel codebase; it remains a Symfony bundle with no supported Laravel path. 6.0.0 does not alter that conclusion, but it does change the value of the package to us: treat it as a higher-quality design and test-case reference than at 5.x, lift the callable-method allowlist and batch-size cap into our native implementation, and mine the changelog for the spec edge cases it fixed. Revisit adoption only if the team standardizes on Symfony.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console