中间件
Middleware
简介
中间件是 Web 应用中极其重要的功能之一,因为它允许您在每次请求之前或之后,甚至在某些路由之前或之后运行重要的代码。在本文档中,我们将讨论中间件的工作原理、如何使用中间件以及如何创建您自己的中间件。中间件只有在找到匹配的路由并且返回状态码为 200 时才会运行。
入门指南
按照约定,中间件类位于 app/http/middleware
目录,但也可以放置在您喜欢的任何位置。所有中间件都只是包含 before
方法和 / 或 after
方法的类。
中间件总共有四种类型:
- 在每次请求之前运行的中间件
- 在每次请求之后运行的中间件
- 在某些路由之前运行的中间件
- 在某些路由之后运行的中间件
在 Masonite 中分为 HTTP 中间件和 Route 中间件,前者是在每次请求中运行的中间件,后者是只在某些请求中调用的中间件,比如检查用户是否登录。
配置
我们需要使用两个配置常量的其中一个。这两个常量都位于我们的 config/middleware.py
文件中,分别是 HTTP_MIDDLEWARE
和 ROUTE_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 响应。
响应中间件
这个中间件接收所提供的响应,并在响应中添加必要的响应头。
中间件参数
如果您想让中间件根据路由的不同而采取不同的行为时,可以将路由中的参数传递给中间件。
您可以在路由中间件名称旁边使用 :
符号,这样就可以把这些参数传递给中间件的 before
和 after
方法。
举个例子,假设我们正在创建一个请求节流的中间件,在我们的路由中,有这样一段内容:
Get('/feeds', 'FeedController').middleware('throttle:2,100')
注意看 throttle:2,100
的语法。2 和 100 将被传递到中间件的 before
和 after
方法中。
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 这个值将传递给中间件的 before
和 after
方法。
创建中间件
同样,中间件应该放置在 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_MIDDLEWARE
和 ROUTE_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 中间件的专家了。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。