I'm trying to build a REST api using Laravel Framework, I want a way to force the API to always responed with JSON not by doing this manulaly like:
return Response::json($data);
In other words I want every response to be JSON. Is there a good way to do that?
Update: The response must be JSON even on exceptions like not found exception.
The json method will automatically convert the array into appropriate json response.
To request JSON from a URL, you need to send an HTTP GET request to the server and provide the Accept: application/json request header with your request. The Accept header tells the server that our client is expecting JSON.
Laravel Request: expectsJson() This function determines if current request expects a json response.
json() The json() method of the Response interface takes a Response stream and reads it to completion. It returns a promise which resolves with the result of parsing the body text as JSON .
Create a middleware as suggested by Alexander Lichter that sets the Accept
header on every request:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class ForceJsonResponse
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
Add it to $routeMiddleware
in the app/Http/Kernel.php
file:
protected $routeMiddleware = [
(...)
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
];
You can now wrap all routes that should return JSON:
Route::group(['middleware' => ['json.response']], function () { ... });
Give the json.response
middleware priority over other middlewares - to handle cases where the request is terminated by other middlewares (such as the Authorize
middleware) before you get to set the Accept
header.
To do this - override the constructor of you App\Http\Kernel
class (app/Http/Kernel.php
) with:
public function __construct( Application $app, Router $router ) {
parent::__construct( $app, $router );
$this->prependToMiddlewarePriority(\App\Http\Middleware\ForceJsonResponse::class);
}
JsonResponseMiddleware
middleware.
php artisan make:middleware JsonResponseMiddleware
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\ResponseFactory;
class JsonResponseMiddleware
{
/**
* @var ResponseFactory
*/
protected $responseFactory;
/**
* JsonResponseMiddleware constructor.
*/
public function __construct(ResponseFactory $responseFactory)
{
$this->responseFactory = $responseFactory;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
// First, set the header so any other middleware knows we're
// dealing with a should-be JSON response.
$request->headers->set('Accept', 'application/json');
// Get the response
$response = $next($request);
// If the response is not strictly a JsonResponse, we make it
if (!$response instanceof JsonResponse) {
$response = $this->responseFactory->json(
$response->content(),
$response->status(),
$response->headers->all()
);
}
return $response;
}
}
App\Http\Kernel.php
protected $middlewareGroups = [
'api' => [
...
....
/// Force to Json response (Our created Middleware)
\App\Http\Middleware\JsonResponseMiddleware::class,
],
'web' => [
...
....
/// Add Here as well if we want to force response in web routes too.
],
]
Now we will receive every response in JSON
only.
Please note that: Even exceptions will respond in JSON format
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With