错误处理

未匹配的标注

Masonite 错误处理基于 ExceptionHandler 类,该类负责处理应用程序抛出的所有异常。

全局异常处理

所有异常都由 ExceptionHandler 类处理,该类通过 exception_handler 键绑定到 服务容器

ExceptionHandler 有一个逻辑来决定如何根据异常类型、环境类型、请求接受的内容类型和 配置的异常处理程序 来处理异常。

默认情况下,程序有一个驱动程序 Exceptionite,它负责通过提供大量上下文来帮助调试你的应用程序来处理开发中的错误。

调试模式

启用 调试模式 时,所有异常都通过 Exceptionite HTML 调试页面呈现。

禁用 调试模式 时,会根据错误类型呈现默认的 errors/500.htmlerrors/404.htmlerrors/403.html 错误页面。

注意:切勿在启用调试模式的情况下在生产环境中部署应用程序!这可能导致暴露一些对最终用户敏感的配置数据和环境变量。

生命周期

当引发异常时,它将被 ExceptionHandler 捕获。然后会发生以下循环:

在开发环境中

  1. 将触发 masonite.exception.SomeException 事件。
  2. 如果给定异常存在特定的 ExceptionHandler,则将使用它。
  3. Exceptionite 将通过在控制台中渲染来处理错误
    • 如果接受的内容是 application/json,则使用 Exceptionite JSON 响应
    • 否则会出现 Exceptionite HTML 错误页面

在生产环境中

  1. 将触发 masonite.exception.SomeException 事件。
  2. 如果给定异常存在特定的 ExceptionHandler,则将使用它。在这种情况下,默认的 ExceptionHandler 将不再处理异常。
  3. 如果异常是 HTTP异常,它将由 HTTPExceptionHandler 负责选择错误模板(errors/500.htmlerrors/404.htmlerrors/403.html)并渲染它。
  4. 如果异常是 Renderable exception,它将被相应地呈现。
  5. 否则此异常尚未处理,将作为具有 500 服务器错误状态代码的 HTTP 异常处理。

报告异常

要报告异常,你应该简单地将其作为任何 Python 异常引发:

def index(self, view:View):
    user = User.find(request.param("id"))
    if not user:
        raise RouteNotFoundException("User not found")

这里有不同类型的异常。

简单的异常

如果没有为简单异常定义 自定义异常处理程序,则将简单异常作为 500 服务器错误处理。

HTTP 异常

HTTP 异常是使用常用 HTTP 状态代码(例如 500、404 或 403)的标准异常。

这些异常将由 HTTPExceptionHandler 呈现,并带有相应的状态代码和相应的默认错误模板(如果它存在于 errors/ 中)。 (请注意,在调试模式下,不会呈现此模板,而是呈现默认的 Exceptionite 错误页面)。

以下 HTTP 异常捆绑到 Masonite 中:

  • 未找到授权异常 (403)
  • 未找到路由异常 (404)
  • 未找到模型异常 (404)
  • 不允许请求相关方法异常 (405)

在默认 Masonite 项目中,现有的错误视图是 errors/404.htmlerrors/403.htmlerrors/500.html。这些视图可以自定义。

你还可以通过设置 is_http_exception=True 并定义 get_response()get_status()get_headers() 方法来构建自定义 HTTP 异常:

class ExpiredToken(Exception):
    is_http_exception = True

    def __init__(self, token):
        super().__init__()
        self.expired_at = token.expired_at

    def get_response(self):
        return "Expired API Token"

    def get_status(self):
        return 401

    def get_headers(self):
        return {
            "X-Expired-At": self.expired_at
        }

当引发上述异常时,Masonite 会在默认项目视图文件夹,并将使用 401 状态代码呈现它。 get_response() 方法的内容将作为消息上下文变量传递给视图。

如果此视图不存在,则 HTML 响应将直接是 get_response() 方法的内容,并带有 401 状态码。

可渲染异常

如果你想在不使用上面的 HTTPExceptionHandler 的情况下更灵活地呈现你的异常,你可以添加一个 get_response() 方法。
此方法将作为 response.view() 的第一个参数给出,以便你可以渲染简单的字符串或自己的视图模板。

class CustomException(Exception):

    def __init__(self, message=""):
        super().__init__(message)
        self.message = message

    def get_response(self):
        return self.message

当你的代码中引发此异常时,Masonite 将知道它应该通过调用 get_response() 方法来呈现它,并且在这里它将呈现为包含引发的消息的字符串。

请注意,你可以通过手动添加 GET_STATUS() 方法,设置一个 HTTP 状态代码来设置 HTTP 异常。

class CustomException(Exception):

    def __init__(self, message=""):
        super().__init__(message)
        self.message = message

    def get_response(self):
        return self.message

    def get_status(self):
        return 401

现有的异常处理程序

现有的异常处理程序有:

  • HTTP 异常处理程序
  • 堆栈异常处理程序

你可以构建自己的异常处理程序来覆盖 Masonite 处理引发的异常的方式或添加新行为。

添加新的处理程序

处理程序是一个简单的类,具有一个 handle() 方法,当应用程序抛出特定异常时,Masonite 将调用该方法。

例如,你可以专门处理应用程序可能抛出的 ZeroDivisionError 异常。它看起来像这样:

class DivideException:

    def __init__(self, application)
        self.application = application

    def handle(self, exception):
        self.application.make('response').view({
            "error": str(exception),
            "message": "You cannot divide by zero"
        }, status=500)

类的名称可以是任何你喜欢的名称。在 handle 方法中,你应该使用 Response 类手动返回响应。

然后,你需要使用特定的键绑定将该类注册到容器中。键绑定将是 {exception_name}Handler。你可以在 Kernel 文件中执行此操作。

要为我们的 ZeroDivisionError 注册一个自定义异常处理程序,我们将创建一个如下所示的绑定:

from app.exceptions.DivideException import DivideException

self.application.bind(
    "ZeroDivisionErrorHandler",
    DivideException(self.application)
)

提示:你可以在 AppProvider 或 Kernel.py 中添加此绑定。

现在,当你的应用程序抛出 ZeroDivisionError 时,Masonite 将使用你的异常处理程序,而不是 Masonite 自己的异常处理程序。

捕获所有异常

如果你想连接诸如 Sentry 或 Rollbar 之类的错误跟踪服务,可以通过事件侦听器执行此操作:每次引发异常时,都会触发 masonite.exception.{TheExceptionType},允许运行任何自定义逻辑。

首先创建一个监听器 来运行你的自定义逻辑:

class SentryListener:

    def handle(self, exception_type: str, exception: Exception):
        # process the exception with Sentry
        # ...

Service Provider 中,你需要注册此监听器:

class AppProvider(Provider):

    def register(self):
        self.application.make("event").listen("masonite.exception.*", [SentryListener])

在默认 Masonite 项目中,现有的错误视图是 errors/404.htmlerrors/403.htmlerrors/500.html

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/masonite/4.0/fe...

译文地址:https://learnku.com/docs/masonite/4.0/fe...

上一篇 下一篇
贡献者:1
讨论数量: 0
发起讨论 只看当前版本


暂无话题~