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]

,它将呈现一个 json 响应 1234563 /p>

这是实现它的一种方法(与上面引用的答案非常相似):

    创建文件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

为啥 Api Route 在 laravel 应用程序中不起作用,显示错误(未找到 404 错误)?

Laravel 5 API 路由向前端返回 500 错误

使用虚拟主机的 Laravel API 返回 404

Laravel 6 API 不会在日志中写入错误 500

Laravel API 路由 404 未找到修复?