Forcing all API requests to accept JSON

Avoid annoying errors

Joel Clermont
Joel Clermont
2024-03-27

When I'm building an API, I usually only design it to accept JSON requests. I think this approach is pretty typical with modern Laravel applications. But by default, Laravel doesn't do anything to enforce this.

API routes will be served to a regular browser user or to an API client that doesn't correctly specify the Accept header. This can even get triggered if someone pastes an API endpoint URL into Slack or some other chat client that tries to load link previews automatically.

This can lead to some annoying errors, especially if your API is expecting Sanctum authentication. For example, if you're building an app that's purely an API with no user interface allowing normal login, you probably don't even have a login route defined in your application. But the Authenticate middleware and other parts of Laravel might try to bounce an unauthenticated user to the login route if they aren't requesting JSON. Now you'll get an HTTP 500 error since it can't resolve the login route.

All of this could be avoided if we just force any request to an API route to accept JSON. I like to do this with a simple middleware:

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);
    }
}

You can either add this middleware to your api middleware group, or to a route group in your routes/api.php file. The key is to make sure it runs before your Authenticate middleware though.

With this in place, you don't get annoying errors and someone trying to hit your API without the header will get a friendly message explaining what they're doing wrong.

Hope this helps,

Joel

P.S. Have you seen Ash Allen's excellent book on Laravel APIs?

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼

Level up your Laravel skills!

Each 2-minute email has real-world advice you can use.