使用中间件和事件

随着蝙蝠侠的应用程序逐渐变得更加复杂,Robyn 向他介绍了中间件、启动和关闭事件,甚至 WebSocket 的使用。蝙蝠侠学会了如何创建中间件(在请求之前或之后执行的函数),如何管理应用程序的生命周期,并通过 WebSocket 实现与客户端的实时通信。

处理事件

蝙蝠侠发现,通过添加启动和关闭事件,他能够有效地管理应用程序的生命周期。为此,他编写了以下代码来定义这些事件:

此外,蝙蝠侠也了解到,事件不仅可以通过函数来定义,还可以使用装饰器的方式来实现。

对于同步请求,蝙蝠侠使用如下代码:

Request

GET
/hello_world
async def startup_handler():
  print("Starting up")

app.startup_handler(startup_handler)

@app.shutdown_handler
def shutdown_handler():
    print("Shutting down")

对于异步请求,蝙蝠侠则使用如下代码:

Request

GET
/hello_world
from robyn import Request

@app.get("/")
async def h(request: Request) -> str:
    return "Hello, world"

POST/http_requests

处理中间件

蝙蝠侠学会了如何在中间件中同时使用同步和异步函数。他编写了以下代码,为每个请求添加了在请求之前和之后执行的中间件。 中间件可以分为两类:请求前中间件和请求后中间件。 该函数在每个请求处理之前执行,可以修改请求对象或执行其他操作。 请求后中间件:该函数在每个请求处理之后执行,可以修改响应对象或执行其他操作。

每个请求前中间件都应接收并返回一个请求对象;每个请求后中间件都应接收并返回一个响应对象。请求后中间件也可以选择性地接收请求对象作为第一个参数,以便访问请求数据。

before_request 链会在其中某个中间件返回响应对象时立即停止:后续的 before_request 中间件以及路由处理函数(主入口)都会被跳过。但 after_request 中间件仍会对该响应执行,然后再返回给客户端——因此可以用它们来处理那些必须始终发生的工作(例如日志、响应头),即使请求被提前中止。

Request

POST
/http_requests
from robyn import Request, Response

@app.before_request("/")
async def hello_before_request(request: Request):
    request.headers.set("before", "sync_before_request")
    return request

@app.after_request("/")
def hello_after_request(response: Response):
    response.headers.set("after", "sync_after_request")
    return response

同一路由上的多个中间件

蝙蝠侠有时需要在请求之前执行不止一件事——比如同时进行日志记录输入清洗,并且常常还要配合身份认证。Robyn 允许你在同一个路由上叠加任意多个 before_requestafter_request 处理函数;它们会按照注册的顺序依次执行。

before_request 链自上而下执行,如果某个处理函数返回了 Response,则提前中止——此时后续的 before_request 中间件和路由处理函数都会被跳过。而 after_request 链始终会按注册顺序对最终返回的响应执行,无论该响应来自路由处理函数还是来自提前返回的 before_request

由于 auth_required=True 本身就是一个 before_request 钩子,它可以和你自己的中间件组合使用:身份认证先执行,然后才是你的自定义过滤器。

多个中间件

GET
/index
from robyn import Request, Response

@app.get("/index", auth_required=True)   # 1. 先执行身份认证
async def index(request: Request):
    return "Index Page"

@app.before_request("/index")            # 2. 然后执行这个
async def log_request(request: Request):
    print("logging:", request.url.path)
    return request

@app.before_request("/index")            # 3. 再执行这个——全部按顺序运行
async def sanitize(request: Request):
    return request

@app.after_request("/index")
async def add_header(response: Response):
    response.headers.set("x-processed", "true")
    return response

下一步

Robyn - 太好了,中间件是 Robyn 框架的重要组件之一,您现在已经掌握了 Robyn 的一些高级概念。

蝙蝠侠 - 身份验证!我想了解身份验证,确保只有经过身份验证的的人才能访问我的应用程序。

Robyn - 好的,接下来我将为您介绍身份验证!