iwf-web/json-request-check-bundle
iwf-web/json-request-check-bundle adds JSON request checking to Symfony applications, helping validate incoming JSON payloads before they reach your controllers. A small integration for more consistent API request handling.
composer require iwf-web/json-request-check-bundle. The package targets Symfony (Flex recipe may not exist, so plan to wire it manually).config/bundles.php:
return [
// ...
Iwf\JsonRequestCheckBundle\JsonRequestCheckBundle::class => ['all' => true],
];
config/packages/json_request_check.yaml. At minimum set a size ceiling so the bundle has something to enforce:
json_request_check:
max_size: 1048576 # bytes, 1 MB
max_depth: 32 # nesting depth
max_keys: 1000 # top-level/scalar key count (HashDos surface)
POST /api/orders), then curl a normal payload (expect 2xx) and an oversized/wide payload (expect a 4xx before your controller/deserializer runs). If the controller never executes for the bad payload, the listener is wired correctly.app/Http/Middleware. Keep that mapping in mind while reading the bundle source — the interesting logic is the payload checker class, not the Symfony glue.Content-Type: application/json detection rather than annotating routes. This is the pattern the bundle is built for and avoids forgetting a new endpoint.json_request_check:
max_size: 65536
paths_excluded:
- ^/api/bulk-import
kernel.request subscribers that read the body (e.g. FOSRest body listeners, API Platform's DeserializeListener). HashDos mitigation is only meaningful if you reject before json_decode allocates the collision-heavy map.max_keys.WebTestCase (or Laravel's TestCase if you port the checker), assert on the status code for three payloads: normal, max_size + 1 bytes, and a deep/wide JSON object that exceeds max_depth/max_keys. This is the regression suite that catches "someone reordered the listeners".handle() before $request->json(). That gives you the HashDos guard without a second HTTP layer.%env(int:JSON_MAX_SIZE)% so ops can tighten limits in production without a deploy — particularly useful during an incident.Content-Type is trusted. If the bundle keys off the header, a client sending text/plain with a JSON body slips past. If downstream code parses it as JSON anyway (or you have a permissive deserializer), the guard is bypassed. Either enforce application/json upstream or confirm the bundle sniffs the body.Content-Length can lie or be absent. Chunked transfer encoding and Transfer-Encoding: gzip mean the header doesn't reflect the decoded body size. Verify whether the check measures the raw stream, the post-decompression size, or trusting the header — and whether that matches your threat model.max_depth and max_keys are actually enforced, not just max_size, or a compact 200 KB payload with 500k keys can still pin a CPU.bin/console debug:event-dispatcher kernel.request) and check priorities. xdebug breaking on the checker class is the fast way to confirm it even fires.Retry-After is nicer than 500, and either is better than a controller-level 422.DependencyInjection/Configuration.php before assuming a key exists. Don't copy snippets from the README without diffing against the installed version."iwf-web/json-request-check-bundle": "0.1.*" or an exact tag) and skim the source before production. The logic is small enough to audit, and porting it to a Laravel middleware is a realistic fallback if Symfony integration is awkward for your stack.How can I help you explore Laravel packages today?