logo
podcast Podcast
get help Get Unstuck

How to enforce max payload size in validation

Not as simple as using a built-in rule

Joel Clermont
Joel Clermont
2024-07-11

Recently, I was building an API endpoint that contained a field which could accept an arbitrary JSON payload. Anything from null, to a simple object, to a deeply nested array.

While we weren't validating any of the contents of the field, we also didn't want to leave it completely open-ended in terms of size. We wanted to enforce a maximum payload size.

1MB seems like a reasonable limit, but how should we enforce it?

We couldn't use the typical max:1024 rule, because this wasn't a file upload. And we didn't want to validate number of characters or array elements.

The solution was to create a custom rule. Here's how I did it:

class MaximumJsonEncodedSize implements ValidationRule
{
    public function __construct(protected int $maxSizeInKilobytes) {}

    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
        if (Str::length(json_encode($value)) > $this->maxSizeInKilobytes * 1024) {
            $fail("The {$attribute} field must not be greater than {$this->maxSizeInKilobytes} kilobytes.");
        }
    }
}

In order to flatten the value out to a string, I used json_encode. This will work for any value, including primitives, arrays and objects.

Technically, encoding adds characters to the payload, so the length calculation isn't 100% precise, but 1MB is such a high limit, it's just here as a sanity check.

I also use the exact validation error you would get if you used max on a file upload field, just to keep things consistent.

Here to help,

Joel

P.S. I can't share a tip on validation without mentioning our book: Mastering Laravel Validation Rules.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.