Laravel 5.5 - 仅记录 500 错误,从不通过 api 发送错误详细信息?

Posted

技术标签:

【中文标题】Laravel 5.5 - 仅记录 500 错误,从不通过 api 发送错误详细信息?【英文标题】:Laravel 5.5 - Only log 500 error, never send error details via api? 【发布时间】:2018-04-29 00:22:10 【问题描述】:

我制作了下面的控制器来演示处理我在使用 api 时遇到的 500 个错误的问题。我希望能够检测到何时会抛出 500 错误,因此它永远不会发送给客户端(因为与客户端共享的细节太多,它们只能由 Laravel 记录)。

由于拼写错误firsgt()getUser() 方法故意返回 500 错误

class TestController extends Controller 
  public function getUser() 
    $data = User::firsgt(); //returns 500 error
    return $data;
  

这是客户看到的:

我们如何才能返回诸如“发生错误”之类的错误消息,而不是客户端“调用未定义方法 App\User::firsgt()”的过多详细信息?

注意:我不想为每个控制器方法一一处理,而是在返回给客户端之前捕获任何 500,并返回自定义的 500 通用消息“发生错误”

【问题讨论】:

【参考方案1】:

如果你想使用来自 Laravel 响应的消息数据,自然地,你需要查找包含消息的响应数据。这仅在 APP_DEBUG=true 时有效,不应在生产中启用,但为了清楚起见:

假设您使用axios 发出请求,它看起来像这样:

axios.get("/api/catalogs/clients/")
                .then(res => 
                    this.client = res.data;
                )
                .catch(e => 
                    print(e.message); //This would print Server error
                    this.clientError = e.response.data.message; //This will print Call to undefined method
                );

【讨论】:

【参考方案2】:

只需更改 .env 文件中的变量,以防止这些消息与响应一起发送。

APP_ENV=生产

APP_DEBUG=false

编辑:只需将 APP_DEBUG 设置为 false 就足够了。

更新: 如果您使用的是 dingo api 包,那么除了将 APP_DEBUG 设置为 false 之外,您还需要编辑配置文件。

如果您还没有完成,请发布 dingo 配置文件

php artisan vendor:publish --provider="Dingo\Api\Provider\LaravelServiceProvider"

然后,打开 config/api.php 并将 errorFormat 值编辑为您想要的任何消息。

:message 替换为通用消息

【讨论】:

这在标准 laravel 上效果很好,但我在使用 dingo api 时遇到了问题。标记为正确,因为它可以帮助其他人和我自己解决 laravel 解决方案(我认为这可以解决我的具体问题),但在与 dingo api 一起使用时不起作用。将为同一问题的 dingo api 版本打开一个问题。【参考方案3】:

错误的详细解释显示在开发环境中,对于生产您不想显示它们-出于安全原因-因此,正如@Hamoud 所述,转到您的.ENV 文件找到该行:

APP_DEBUG=true

改成:

APP_DEBUG=false

这将仅显示标准错误响应。查看有关error details 的文档。

【讨论】:

【参考方案4】:

您有 app/Exception/Handler.php 类来执行此操作。例如你可以使用类似这样的代码:

public function render($request, Exception $e)

    $exception_class = get_class($e);

    if (!in_array($exception_class, [ValidationException::class, ModelNotFoundException::class] ) 
       return response()->json(['info' => 'Error occurred'], 500);
    

   return parent::render();

但正如您所见,您应该排除一些您希望以正常方式呈现的异常类,这里只是一些示例异常类。

显然,如果您正在设计 API,可能根本没有必要使用 parent::render(),您应该以自定义方式处理自定义异常类,然后最后对于其他异常,只需返回 500 响应以及您想要的消息。

【讨论】:

谢谢你,我为 laravel 找到了,只做APP_DEBUG = false 要容易得多,所以它可以安全地处理错误/通常为客户“发生错误”。我的问题仍然存在,但与 dingo api 相关,所以我打开了同样的问题,但针对 dingo api。【参考方案5】:

Laravel 已经为您完成了这项工作,但前提是您处于生产模式并且请求需要 JSON。

无论如何,App\Exceptions\Handler 类是可以处理所有异常的地方。它也是 Laravel 自己记录和渲染所有异常的地方。

public function render($request, Exception $exception)

    // your logic here

    return parent::render($request, $exception);

【讨论】:

【参考方案6】:

您可以使用try ... catch

try
   .....
catch(\Exception $e)
  if($e->getCode() == 500)
      return response()->json(["error"=>'$e->getCode()'],500);
  

【讨论】:

true,但我不想在我的代码中为所有控制器方法显式使用 try catch。只是一种简单的全局方法来处理任何 500 次 laravel 抛出并捕获冒泡的错误。

以上是关于Laravel 5.5 - 仅记录 500 错误,从不通过 api 发送错误详细信息?的主要内容,如果未能解决你的问题,请参考以下文章

Cpanel 共享主机中的 Laravel 5.5 错误 500

Laravel 5.5 无法使用身份验证脚手架登录

如何在 laravel 5.5 中使用 phpunit 测试中间件?

检查 Laravel 5.5 中是不是存在记录 [关闭]

为啥我的 laravel 集合返回 500 错误,即使不是在我使用 dd() 检查结果时?

Laravel:致命错误:内存字节用尽远程数据库