Laravel 404 和 500 的 API 和网站中的不同响应(JSON 和网页)?
Posted
技术标签:
【中文标题】Laravel 404 和 500 的 API 和网站中的不同响应(JSON 和网页)?【英文标题】:Different Response(JSON and webpage) in API and Website for Laravel 404 and 500? 【发布时间】:2017-09-24 18:56:48 【问题描述】:我想显示 API 和网站的不同响应。在 api 响应中,我想显示带有 404 和 500 的 json 响应,主要用于路由的异常类型。
如果用户尝试请求路由并且找不到路由,我想在 API 的 json 响应和网站的网页中显示响应。
我知道并尝试将代码放入app/Exceptions/Handler.php
public function render($request, Exception $exception)
if ($exception instanceof NotFoundHttpException)
if ($request->expectsJson())
return response()->json(['error' => 'Not Found'], 404);
return response()->view('404', [], 404);
return parent::render($request, $exception);
https://laravel.com/docs/5.4/errors#http-exceptions
但是失败了谁能帮助我如何为错误页面设置不同的响应。
【问题讨论】:
对于 Laravel 8,请参阅此答案***.com/a/60671373/9053821 【参考方案1】:try this.
public function render($request, Exception $exception)
if ($request->ajax())
return \Response::json([
'success' => false,
'message' => $exception->getMessage(),
], $exception->getCode());
else
return parent::render($request, $exception);
【讨论】:
"X-Requested-With":"XMLHttpReques" 需要在标头中添加,否则 laravel 请求不会检测为 ajax 调用,为什么要返回页面。【参考方案2】:期望JSON
是关于标题的,我不喜欢API
错误的解决方案,您可以通过浏览器访问API
。我的解决方案大部分时间是通过URL
路由进行过滤,因为它以"api/..."
开头,可以像$request->is('api/*')
那样完成。
如果您的路由不是以/api
为前缀的,那么这将不起作用。更改逻辑以适合您自己的结构。
public function render($request, Exception $exception)
if ($exception instanceof NotFoundHttpException)
if ($request->is('api/*'))
return response()->json(['error' => 'Not Found'], 404);
return response()->view('404', [], 404);
return parent::render($request, $exception);
【讨论】:
这对我有用,也加use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
Thankyou【参考方案3】:
我正在使用 Laravel 5.5.28,并将其添加到 app/Exceptions/Handler.php
public function render($request, Exception $exception)
// Give detailed stacktrace error info if APP_DEBUG is true in the .env
if ($request->wantsJson())
// Return reasonable response if trying to, for instance, delete nonexistent resource id.
if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException)
return response()->json(['data' => 'Resource not found'], 404);
if ($_ENV['APP_DEBUG'] == 'false')
return response()->json(['error' => 'Unknown error'], 400);
return parent::render($request, $exception);
这预计您的 API 调用将具有带有键 Accept
和值 application/json
的标头。
然后一个不存在的网络路由返回预期
抱歉,找不到您要查找的页面
并且不存在的 API 资源返回 JSON 404 有效负载。
找到info here。
您可以将此与寻找 NotFoundHttpException
实例的答案结合起来以捕获 500。但是,我想堆栈跟踪将是首选。
【讨论】:
【参考方案4】:无需再为 Laravel 升级而忙碌。你只需要在routes/api.php
中定义这个方法Route::fallback(function()
return response()->json(['message' => 'Not Found!'], 404);
);
【讨论】:
这适用于 GET 方法。但与其他方法(POST,PUT,...)相同的 url 返回 405 MethodNotAlowed。我建议通过这种方式在您的 api 路由末尾定义自定义后备路由(***.com/a/47537029/6807353)【参考方案5】:只是想为上述答案添加一个替代方案,所有这些似乎都有效。
在遇到同样的问题并深入挖掘之后,我采取了稍微不同的方法:
您的异常句柄调用parent::render(...)
。如果您查看该函数,如果您的请求表明它wantsJson()
[参见hints how that works here]
这是实现它的一种方法(与上面引用的答案非常相似):
创建文件app/Http/Middleware/Jsonify.php
<?php
namespace App\Http\Middleware;
use Closure;
class Jsonify
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
if ( $request->is('api/*') )
$request->headers->set('Accept', 'application/json');
return $next($request);
将中间件引用添加到 app/Http/Kernel.php
文件的 $routeMiddleware 表中:
protected $routeMiddleware = [
...
'jsonify' => \App\Http\Middleware\Jsonify::class,
...
];
在同一个内核文件中,将 jsonify 名称添加到 api 组:
protected $middlewareGroups = [
...
'api' => [
'jsonify',
'throttle:60,1',
'bindings',
],
...
];
结果是任何属于“api”组的请求都会加载中间件。如果请求 url 以 api/
开头(我认为这有点多余),那么 Jsonify 中间件会添加标头。这将告诉 ExceptionHandler::render() 我们想要一个 json 输出。
【讨论】:
遗憾的是,这在大多数情况下都有效,但在某些情况下它不起作用:如果您从策略或门中获得“未授权”,那么您的中间件可能尚未加载.如果没有加载 jsonify,除非您相应地设置标题(接受应用程序/Json),否则您将获得非 json 输出。所以你可以使用这个答案,只是要注意不足之处...... 如果您将此添加到api
中间件组,则无需在请求 URL 中检查 /api
。路由服务提供商将api
中间件组和/api
前缀应用于api.php
中列出的路由。以上是关于Laravel 404 和 500 的 API 和网站中的不同响应(JSON 和网页)?的主要内容,如果未能解决你的问题,请参考以下文章
API POST 请求在邮递员和 Laravel 上返回 404 NOT FOUND PAGE