中间件

未匹配的标注
本文档最新版为 4.0,旧版本可能放弃维护,推荐阅读最新版!

Middleware

简介

中间件是 Web 应用中极其重要的功能之一,因为它允许您在每次请求之前或之后,甚至在某些路由之前或之后运行重要的代码。在本文档中,我们将讨论中间件的工作原理、如何使用中间件以及如何创建您自己的中间件。中间件只有在找到匹配的路由并且返回状态码为 200 时才会运行。

入门指南

按照约定,中间件类位于 app/http/middleware 目录,但也可以放置在您喜欢的任何位置。所有中间件都只是包含 before 方法和 / 或 after 方法的类。

中间件总共有四种类型:

  • 在每次请求之前运行的中间件
  • 在每次请求之后运行的中间件
  • 在某些路由之前运行的中间件
  • 在某些路由之后运行的中间件

在 Masonite 中分为 HTTP 中间件和 Route 中间件,前者是在每次请求中运行的中间件,后者是只在某些请求中调用的中间件,比如检查用户是否登录。

配置

我们需要使用两个配置常量的其中一个。这两个常量都位于我们的 config/middleware.py 文件中,分别是 HTTP_MIDDLEWAREROUTE_MIDDLEWARE

HTTP_MIDDLEWARE 是一个包含中间件类集合的简单列表。因为这个常量是一个列表,所以里面的中间件都会一个接一个地依次运行,类似于 Django 的中间件。

中间件是一个字符串,指向您的中间件类的所在位置。如果您的类位于 app/http/middleware/DashboardMiddleware.py 中,那么我们在中间件配置中的值应该是一个字符串: app.http.middleware.DashboardMiddleware.DashboardMiddleware。Masonite 会定位该类并执行 before 方法或 after 方法。

在我们的 config/middleware.py 文件中,HTTP 中间件如下所示:

from app.http.middleware.DashboardMiddleware import DashboardMiddleware

HTTP_MIDDLEWARE = [
    DashboardMiddleware,
]

路由中间件

ROUTE_MIDDLEWARE 也很简单,但它不是一个列表,而是一个字典,以自定义名称作为键,中间件类作为值。这样我们就可以根据路由文件中的键指定中间件了。

在我们的 config/middleware.py 文件中,路由中间件如下所示:

from app.http.middleware.RouteMiddleware import RouteMiddleware

ROUTE_MIDDLEWARE = {
    'auth': RouteMiddleware,
}

中间件堆栈

路由中间件有一个独特之处,那就是路由中间件也可以作为中间件的堆栈(或者说是列表)。也就是说,我们可以指定一个包含列表的中间件,而不是只能基于字符串指定中间件:

from app.http.middleware.AdminMiddleware import AdminMiddleware
from app.http.middleware.AuthMiddleware import AuthMiddleware
from app.http.middleware.VerifyMiddleware import VerifyMiddleware

ROUTE_MIDDLEWARE = {
    'admin': AdminMiddleware,
    'auth': [
        AuthMiddleware,
        VerifyMiddleware,
    ]
}

注意,我们可以同时使用列表和字符串作为中间件。作为列表时,当我们调用 auth 中间件堆栈,列表中的所有中间件都会执行。

默认中间件

Masonite 自带了几个默认的中间件。这些中间件可以被更改或删除,以更好地适应您的应用。

身份认证中间件

设计这个中间件的目的是为了在用户没有登录时重定向到登录页面。它位于 config/middleware.py 文件中,作为路由中间件加载,并且只在您指定的路由上运行。

您可以在任何路由上调用这个中间件,通过路由的中间件方法:

routes/web.py

from masonite.routes import Get
...

ROUTES = [
    ...
    Get('/dashboard', 'DashboardController@show').middleware('auth')
]

验证 Email 中间件

这个中间件检查已登录的用户是否验证了他们的 Email。如果没有,它会把用户重定向到一个提醒他们验证 Email 的页面。

您可以在任何路由上调用这个中间件,只需在路由中间件方法中指定即可:

routes/web.py

from masonite.routes import Get
...

ROUTES = [
    ...
    Get('/dashboard', 'DashboardController@show').middleware('verified')
]

CSRF 中间件

这个中间件是一个 HTTP 中间件,在每次请求中执行。这个中间件会在 POST 请求中检查 CSRF 令牌。对于 GET 请求,Masonite 会生成一个新的令牌。默认行为适用于大多数应用,但您也可以修改它以更好地适应您的应用。

加载用户中间件

这个中间件检查用户是否登录,如果已登录,就把该用户加载到请求对象中。您可以像下面这样使用它:

app/http/controllers/YourController.py

def show(self):
    return request().user() # 返回这个用户 或 None

Json 响应中间件

这个中间件会把字典响应转换成 JSON 响应。

响应中间件

这个中间件接收所提供的响应,并在响应中添加必要的响应头。

中间件参数

如果您想让中间件根据路由的不同而采取不同的行为时,可以将路由中的参数传递给中间件。

您可以在路由中间件名称旁边使用 : 符号,这样就可以把这些参数传递给中间件的 beforeafter 方法。

举个例子,假设我们正在创建一个请求节流的中间件,在我们的路由中,有这样一段内容:

Get('/feeds', 'FeedController').middleware('throttle:2,100')

注意看 throttle:2,100 的语法。2 和 100 将被传递到中间件的 beforeafter 方法中。

class ThrottleMiddleware:

    def before(self, minutes, requests):
        # throttle requests

    def after(self, minutes, requests):
        # throttle requests

请求参数

与使用 : 拼接的方式类似,我们也可以使用 @ 来传递参数的值。

举个例子,我们创建这样的路由和中间件:

Get('/dashboard/@user_id/settings', 'FeedController').middleware('permission:@user_id')

如果我们进入 /dashboard/152/settings 这个路由,那么 152 这个值将传递给中间件的 beforeafter 方法。

创建中间件

同样,中间件应该放置在 app/http/middleware 文件夹中,如下所示:

class AuthenticationMiddleware:
    """Middleware class
    """

    def __init__(self, request: Request):
        self.request = request

    def before(self):
        pass

    def after(self):
        pass

中间件构造函数由容器解析,因此只需传入参数列表中的任意参数,它就会被注入。

更多信息请参阅 服务容器 文档.

如果 Masonite 正在执行一个 before 中间件,也就是应该在请求之前执行的中间件,Masonite 会检查所有的中间件,寻找一个 before 方法并执行它。对于 after 中间件也是如此。

如果您不希望中间件在此之前或之后运行,您可以排除任何一种方法。

下面是一个中间件的示例。它只是一个带有 before 和 / 或 after 方法的类。创建一个中间件就是这么简单。让我们创建一个中间件,用来检查用户是否通过了身份验证,如果没有,则重定向到登录页面。因为我们可以从服务容器中访问请求对象,所以我们可以这样写:

class AuthenticationMiddleware:
    """将当前用户加载到请求中的中间件类"""

    def __init__(self, request: Request):
        self.request = request

    def before(self):
        if not self.request.user():
            self.request.redirect_to('login')

    def after(self):
        pass

就是这样!现在我们只需要确保我们的路由能接收到这个信息。如果我们希望在请求之后执行此操作,则可以在 after 方法中使用完全相同的逻辑。

由于我们没有使用 after 方法,所以我们可以将其全部排除。Masonite 会在执行之前检查该方法是否存在。

配置

我们需要使用两个配置常量的其中一个。这两个常量都位于我们的 config/middleware.py 文件中,分别是 HTTP_MIDDLEWAREROUTE_MIDDLEWARE

HTTP_MIDDLEWARE 是一个包含中间件类集合的简单列表。因为这个常量是一个列表,所以里面的中间件都会一个接一个地依次运行,类似于 Django 的中间件。

中间件是一个字符串,指向您的中间件类的所在位置。如果您的类位于 app/http/middleware/DashboardMiddleware.py 中,那么我们在中间件配置中的值应该是一个字符串: app.http.middleware.DashboardMiddleware.DashboardMiddleware。Masonite 会定位该类并执行 before 方法或 after 方法。

在我们的 config/middleware.py 文件中,HTTP 中间件如下所示:

from app.http.middleware.DashboardMiddleware import DashboardMiddleware

HTTP_MIDDLEWARE = [
    DashboardMiddleware,
]

ROUTE_MIDDLEWARE 也很简单,但它不是一个列表,而是一个字典,以自定义名称作为键,中间件类作为值。这样我们就可以根据路由文件中的键指定中间件了。

在我们的 config/middleware.py 文件中,路由中间件如下所示:

from app.http.middleware.RouteMiddleware import RouteMiddleware

ROUTE_MIDDLEWARE = {
    'auth': RouteMiddleware,
}

使用中间件

使用中间件也很简单。如果我们把中间件放在 HTTP_MIDDLEWARE 常量中,那么我们就不用再担心了。它将在每一次成功的请求中执行,也就是从我们的 web.py 文件中找到匹配的路由时。

如果我们使用的是路由中间件,我们需要指定哪个路由应该调用中间件。要指定哪个路由,只需将 .middleware() 方法附加到路由上即可。如下所示:

Get().route('/dashboard', 'DashboardController@show').name('dashboard').middleware('auth')
Get().route('/login', 'LoginController@show').name('login')

这将会在用户访问 /dashboard 网址时执行 auth 中间件,并且按照我们的中间件,用户会被重定向到 login 的命名路由。

太棒了!你现在是 Masonite 中间件的专家了。

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

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

原文地址:https://learnku.com/docs/masonite/2.3/ad...

译文地址:https://learnku.com/docs/masonite/2.3/ad...

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


暂无话题~