我正在尝试使用Laravel Framework构建REST api,我想要一种强制API始终使用JSON进行响应的方法,而不是通过这样做:
return Response::json($data);
换句话说,我希望每个响应都是JSON。有没有办法做到这一点?
更新:即使未找到异常,响应也必须是JSON 异常。
答案 0 :(得分:5)
仅在JSON
return $data;
要对错误做出JSON
响应,请转到app\Exceptions\Handler.php
文件,然后查看render
方法。
你应该能够重写它看起来像这样:
public function render($request, Exception $e)
{
// turn $e into an array.
// this is sending status code of 500
// get headers from $request.
return response()->json($e, 500);
}
但是,您必须决定如何处理$e
,因为它必须是array
。您还可以设置状态代码和标题数组。
但是,如果出现任何错误,它将返回JSON
响应。
编辑:还可以注意到,您可以更改report
方法来处理laravel如何记录错误。更多信息here。
答案 1 :(得分:2)
JsonResponseMiddleware
中间件。
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.
],
]
现在,我们将仅在JSON
中收到每个答复。
注意:异常也是如此
答案 2 :(得分:1)
按照Alexander Lichter的建议创建一个中间件,该中间件在每个请求上设置Accept
头:
<?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);
}
}
将其添加到$routeMiddleware
文件中的app/Http/Kernel.php
:
protected $routeMiddleware = [
(...)
'json.response' => \App\Http\Middleware\ForceJsonResponse::class,
];
您现在可以包装所有应返回JSON的路由:
Route::group(['middleware' => ['json.response']], function () { ... });
答案 3 :(得分:1)
我使用了这里也提到的几种混合解决方案,以解决所有问题。原因是这里总是在“ / api”下面的每个请求上回复一个json响应。
app/Http/Middleware/ForceJsonResponse.php
中进行JSON输出<?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)
{
// set Accept request header to application/json
$request->headers->set('Accept', 'application/json');
return $next($request);
}
}
app/Http/Kernel.php
的api数组的 TOP 上 protected $middlewareGroups = [
...
'api' => [
\App\Http\Middleware\ForceJsonResponse::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
...
];
app/Exceptions/Handler.php
来响应 namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+ use Throwable;
class Handler extends ExceptionHandler
{
...
+ /**
+ * Render an exception into an HTTP response.
+ *
+ * @param \Illuminate\Http\Request $request
+ * @param \Throwable $e
+ * @return \Illuminate\Http\Response
+ */
+ public function render($request, Throwable $e)
+ {
+ // Force to application/json rendering on API calls
+ if ($request->is('api*')) {
+ // set Accept request header to application/json
+ $request->headers->set('Accept', 'application/json');
+ }
+
+ // Default to the parent class' implementation of handler
+ return parent::render($request, $e);
+ }
}
答案 4 :(得分:0)
我知道已经回答了这个问题,但是这些不是很好的解决方案,因为它们以无法预测的方式更改状态代码。最好的解决方案是添加适当的标头,以使Laravel返回JSON(我认为是Accept: application/json
),或者按照此出色的教程来始终告诉Laravel返回JSON:https://hackernoon.com/always-return-json-with-laravel-api-870c46c5efb2
如果您想更具选择性或适应更复杂的解决方案,也可以通过中间件来实现。
答案 5 :(得分:0)