Laravel 404和500的API和网站中的不同响应(JSON和网页)?

时间:2017-04-27 06:18:31

标签: laravel laravel-5.4

我想展示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

但是失败的任何人都可以帮助我如何为错误页面设置不同的响应。

5 个答案:

答案 0 :(得分:7)

期待JSON是关于标题的,我不喜欢API错误的解决方案,说实话,您可以通过浏览器访问它。大多数情况下,我的解决方案是按网址路由进行过滤,因为它通常以"api/..."开头,可以这样做$request->is('api/*')

如果您有/ 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);
}

答案 1 :(得分:2)

只想为上述答案添加一个替代方法,这些方法似乎也都可以使用。

遇到相同的问题并深入研究之后,我采取了略有不同的方法:

  • 您的异常句柄调用parent::render(...)。如果您查看该函数,则如果您的请求指示wantsJson() [请参见hints how that works here]

  • ,它将呈现一个json响应。
  • 现在,要将所有响应(包括异常)转换为json,我使用了here中的Jsonify中间件思想,但将其应用于api MiddlewareGroup,该API默认情况下分配给RouteServiceProvider :: mapApiRoutes( )

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

  1. 创建文件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);
        }
    }
    
  2. 将中间件引用添加到app/Http/Kernel.php文件的$ routeMiddleware表中:

        protected $routeMiddleware = [
        ...
           'jsonify' => \App\Http\Middleware\Jsonify::class,
        ...
        ];
    
  3. 在同一内核文件中,将jsonify名称添加到api组:

    protected $middlewareGroups = [
    ...
      'api' => [
        'jsonify',
        'throttle:60,1',
        'bindings',            
      ],
    ...
    ];
    

结果是为属于“ api”组的所有请求加载了中间件。如果请求url以api/开头(我认为这有点多余),那么头将由Jsonify中间件添加。这将告诉ExceptionHandler :: render()我们想要一个json输出。

答案 2 :(得分:0)

我正在使用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的标头。

然后,不存在的Web路由返回预期的

  

抱歉,找不到您要找的页面

且不存在的API资源返回JSON 404有效负载。

找到info here

您可以将此与寻找NotFoundHttpException实例的答案结合起来以捕获500.但我想,堆栈跟踪将是首选。

答案 3 :(得分:0)

无需费心去进行Laravel升级。您只需要在 routes / api.php

中定义此方法
Route::fallback(function(){
    return response()->json(['message' => 'Not Found!'], 404);
});

查看此链接以获取大部分为不良回答的回复Better 404 Responses

答案 4 :(得分:-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);
        }
    }