Laravel Lumen Ensure JSON response
You'll need to adjust your exception handler (app/Exceptions/Handler.php
) to return the response you want.
This is a very basic example of what can be done.
public function render($request, Exception $e){ $rendered = parent::render($request, $e); return response()->json([ 'error' => [ 'code' => $rendered->getStatusCode(), 'message' => $e->getMessage(), ] ], $rendered->getStatusCode());}
A more accurate solution based on @Wader's answer can be:
use Illuminate\Http\JsonResponse;public function render($request, Exception $e){ $parentRender = parent::render($request, $e); // if parent returns a JsonResponse // for example in case of a ValidationException if ($parentRender instanceof JsonResponse) { return $parentRender; } return new JsonResponse([ 'message' => $e instanceof HttpException ? $e->getMessage() : 'Server Error', ], $parentRender->status());}
Instead of touching the exception handler, I suggest you to add a middleware that sets the Accept
header to application/json
.
For example, you can create a middleware called RequestsAcceptJson
and define it this way:
<?phpnamespace App\Http\Middleware;use Closure;class RequestsAcceptJson{ /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { $acceptHeader = strtolower($request->headers->get('accept')); // If the accept header is not set to application/json // We attach it and continue the request if ($acceptHeader !== 'application/json') { $request->headers->set('Accept', 'application/json'); } return $next($request); }}
Then you only need to register it as a global middleware to be run in every request to your api. In lumen you can do that by adding the class in the middleware call inside your bootstrap/app.php
$app->middleware([ App\Http\Middleware\RequestsAcceptJson::class]);
With Laravel it's pretty much the same process. Now the error handler will always return a json instead of plain text/html.