logo
podcast Podcast
get help Get Unstuck

How to enforce all API requests are JSON

Cut down on confusion and support requests

Joel Clermont
Joel Clermont
2024-07-15

I got some feedback on a recent tip about the importance of API specs, and it sparked an idea for today's tip.

In Laravel, responses are sent differently, even for API routes, based on the way that the client makes the request. There are two examples that come to mind:

  1. Let's say someone makes a request, but does not specify Accept: application/json in the header, and the request throws an exception. Laravel will return an HTML response with the exception message because of the missing header.
  2. Same scenario of the missing Accept header, but this time they have an invalid bearer token (or whatever your auth mechanism is). Laravel will try to redirect them to the "login" route.

The first scenario is annoying to the API caller, even though it's technically their fault, but it can generate support requests.

The second scenario is problematic in an API-only project because you might not even have a login route, and now you'll throw a RouteNotFoundException.

So how do I deal with this? I add this simple middleware to my API route group:

class RequiresJson
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!$request->wantsJson()) {
            throw new NotAcceptableHttpException(
                'Please request with HTTP header: Accept: application/json'
            );
        }

        return $next($request);
    }
}

Now any request to an API route that is missing the proper Accept header will get an HTTP 406 response with a human-friendly error message.

This cuts down on confusion and support requests.

Here to help,

Joel

P.S. Something in your app generating more customer support tickets than you'd like? Let's pair on it!

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.