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;
}
}
2.在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.
],
]
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);
}
<?php
namespace App\Http;
use Illuminate\Http\Request as BaseRequest;
use Illuminate\Support\Str;
class Request extends BaseRequest
{
public function wantsJson(): bool
{
return Str::startsWith($this->path(), 'api/') || parent::wantsJson();
}
}
9条答案
按热度按时间piztneat1#
按照Alexander Lichter的建议创建一个中间件,在每个请求上设置
Accept
头:将其添加到
app/Http/Kernel.php
文件中的$routeMiddleware
:你现在可以 Package 所有应该返回JSON的路由:
编辑:适用于Laravel 6.9+
给予
json.response
中间件高于其他中间件的优先级-以处理在设置Accept
头之前请求被其他中间件(如Authorize
中间件)终止的情况。要做到这一点-重写
App\Http\Kernel
类(app/Http/Kernel.php
)的构造函数:mfuanj7w2#
Laravel中间件在这个用例中非常有用。
1.制作
JsonResponseMiddleware
中间件。php artisan make:middleware JsonResponseMiddleware
2.在
App\Http\Kernel.php
中注册中间件现在我们将只接收
JSON
中的每个响应。请注意:即使异常也会以JSON格式响应
nuypyhwy3#
我知道这个问题已经得到了回答,但这些都不是好的解决方案,因为它们以不可预测的方式改变了状态代码。最好的解决方案是添加适当的头部,以便Laravel返回JSON(我认为是
Accept: application/json
),或者遵循这个伟大的教程总是告诉Laravel返回JSON:https://hackernoon.com/always-return-json-with-laravel-api-870c46c5efb2如果您希望更具选择性或适应更复杂的解决方案,您也可以通过中间件来实现这一点。
dnph8jn44#
要在控制器中返回
JSON
,只需return $data;
要获得
JSON
对错误的响应,请转到app\Exceptions\Handler.php
文件并查看render
方法。你应该能够重写它,看起来像这样:
但是,您必须决定如何处理
$e
,因为它必须是array
。您还可以设置状态代码和标题数组。但是在任何错误时,它都会返回
JSON
响应。report
方法来处理laravel如何记录错误。更多信息请点击此处。*piv4azn75#
我已经使用了几个混合解决方案,也在这里提到,以解决一切有点更动态。原因是总是在“/API”下面用json响应回复每个请求。
1.创建一个中间件来强制
app/Http/Middleware/ForceJsonResponse.php
中的JSON输出1.将此新中间件添加到
app/Http/Kernel.php
中API阵列的 TOP 上1.覆盖异常处理程序的呈现方法,所有异常也使用JSON
app/Exceptions/Handler.php
进行响应9fkzdhlc6#
另一个简单的解决方案是扩展Request类。使用以下命令创建
app/Http/Request.php
然后在
public/index.php
中添加:olqngx597#
您可以创建一个After Middleware并更改所有响应的结构
中间件:
该中间件将强制响应内容为
0lvr5msh8#
在Laravel 10上尝试了这个,我认为这是更干净的,无需修改/创建新的或框架文件:
在回调函数中设置请求头
yuvru6vn9#
您不应该修改请求头,因为它可能无法反映用户真正想要的内容,一般来说,这不是一个很好的做法
有一种更简单的方法可以做到这一点:重写
ExceptionHandler
中的shouldReturnJson()
方法默认情况下,它是
return $request->expectsJson()
,但您可以将其重写为(“expect json”或“from API route”)“from API route”部分可以通过多种方式实现,你可以检查它是否在“API”中间件组中,就像我做的那样:
in_array('api',$request->route()->getAction('middleware'))
或检查当前URI是否以“API/”开头:Str::startsWith($request->path(), 'api/')
即使使用
Authenticate
中间件也是如此,因为AUthenticate中间件实际上抛出了一个Illuminate\Auth\AuthenticationException
,让Handler
处理因此,通过此更改,所有错误都将以json形式从API路由返回,包括未经身份验证的错误,而无需设置
Accept: application/json
头