Skip to content

Instantly share code, notes, and snippets.

@meSingh
Last active July 11, 2022 09:19
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save meSingh/c90c5abc81a9cc0687a62a84eb2c696b to your computer and use it in GitHub Desktop.
Save meSingh/c90c5abc81a9cc0687a62a84eb2c696b to your computer and use it in GitHub Desktop.
If you are using laravel as api only, you might want to return JSON on every request, even on errors/exceptions. The easiest way to do so is using this middleware globally.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class JsonMiddleware
{
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
@meSingh
Copy link
Author

meSingh commented May 4, 2018

Originally shared by Alexander Lichter
https://twitter.com/TheAlexLichter/status/969879256271597568

@andreshg112
Copy link

Hi, thank you so much!
I noticed something. When a NotFoundHttpException happens because of sending a model id that doesn't exist via path parameter, the error is not displayed in JSON (unless you manually add the header). In the next code you can see how I solved it:

app/Exceptions/Handler.php

    public function render($request, Exception $exception)
    {
        if (in_array('api', $request->route()->middleware())) {
            $request->headers->set('Accept', 'application/json');
        }

        return parent::render($request, $exception);
    }

@andreshg112
Copy link

andreshg112 commented Jul 25, 2018

My workaround doesn't work in Laravel 5.4.
Yours works in Laravel 5.4 only when the validation is not using a Form Request.

@skcin7
Copy link

skcin7 commented Dec 14, 2018

It seems this middleware only works when it is a global middleware. When moved into the web or api routes, it does not seem to work.

@kiwina
Copy link

kiwina commented Dec 19, 2018

It seems this middleware only works when it is a global middleware. When moved into the web or api routes, it does not seem to work.

You have to add it as first middleware in the api group

@baj84
Copy link

baj84 commented Mar 25, 2019

thanks!

@lorisleiva
Copy link

You can place that middleware wherever you want in your middleware groups, just make sure that it's defined first in the $middlewarePriority array.

    protected $middlewarePriority = [
        \App\Http\Middleware\JsonOnlyMiddleware::class, // <- Make it the top priority middleware
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Illuminate\Auth\Middleware\Authorize::class,
    ];

If you cannot see that array in your Http Kernel, copy/paste it from the parent class: Illuminate\Foundation\Http\Kernel. (I think it's been removed from 7.x by default).

@itorgov
Copy link

itorgov commented Apr 20, 2020

Hi, thank you so much!
I noticed something. When a NotFoundHttpException happens because of sending a model id that doesn't exist via path parameter, the error is not displayed in JSON (unless you manually add the header). In the next code you can see how I solved it:

app/Exceptions/Handler.php

    public function render($request, Exception $exception)
    {
        if (in_array('api', $request->route()->middleware())) {
            $request->headers->set('Accept', 'application/json');
        }

        return parent::render($request, $exception);
    }

When it's a 404 error (route not found) there will be an exception, because $request->route() will return null.
I just change it a little:

if ($request->route() !== null && in_array('api', $request->route()->middleware())) {
    $request->headers->set('Accept', 'application/json');
}

But with this fix you'll get an HTML response as default in case when it's 404 error.

@getmanzooronline
Copy link

If you need 404 also in JSON, update the render function as follows. This solved for me in Laravel 6

app/Exceptions/Handler.php

public function render($request, Exception $exception)
{
        if (substr($request->server()['REQUEST_URI'],1,3) =='api') {
            $request->headers->set('Accept', 'application/json');
        }
        return parent::render($request, $exception);
}

@harryqt
Copy link

harryqt commented Jul 11, 2022

Returns "text/html; charset=UTF-8"

Route::get('/foo', function () {
    return 'hello world';
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment