11. 中间件和监听
你的鼓励是我前进的动力,请为我点个赞吧!
Sanic中间件在请求之前或者响应之后运行,开发者可以根据自己的想法有意识的修改请求或者响应。
Sanic提供了监听器来处理来自不同应用的循环请求。
(1)中间件
Sanci提供了两类中间件:请求和响应中间件,开发者可以使用@app.middleware进行中间件响应和声明,在进行中间声明的时候要参数设置来说明是请求/响应中间件。
注意:
- 请求中间件只接受请求(request)作为参数
- 响应中间件请求(request)和响应(response)参数
以下中间件并不更改请求和响应。
@app.middleware('request')
async def print_on_request(request):
print("I print when a request is received by the server")
@app.middleware('response')
async def print_on_response(request, response):
print("I print when a response is returned by the server")
(2)修改请求和响应
中间件可以修改请求和响应,只要不返回该参数,具体示例如下所示:
app = Sanic(__name__)
@app.middleware('request') async def add_key(request):
# Add a key to request object like dict object
request['foo'] = 'bar'
@app.middleware('response') async def custom_banner(request, response):
response.headers["Server"] = "Fake-Server"
@app.middleware('response') async def prevent_xss(request, response):
response.headers["x-xss-protection"] = "1; mode=block"
app.run(host="0.0.0.0", port=8000)
以上代码定义了3个中间件,第一个中间件在request对象中添加了一个foo属性。第二个方法进行头添加,第三个方法是添加了一个头,后面两个函数要在response之后执行。
(3)响应提前
假如中间件将响应提前返回给客户端,请求将会停止,并且响应将会返回。如果响应在请求视图函数处理之前执行那么,用户定义的函数将永远不会执行,返回响应可以组织任何一个中间件运行。
@app.middleware('request')
async def halt_request(request):
return text('I halted the request')
@app.middleware('response')
async def halt_response(request, response):
return text('I halted the response')
(4)监听器
Sanic提供了中间件
- before_server_start
- after_server_start
- before_server_stop
- after_server_stop
这些监听器是作为函数的装饰器实现的,这些函数接受app对象和asyncio循环。
@app.listener('before_server_start')
async def setup_db(app, loop):
app.db = await db_setup()
@app.listener('after_server_start')
async def notify_server_started(app, loop):
print('Server successfully started!')
@app.listener('before_server_stop')
async def notify_server_stopping(app, loop):
print('Server shutting down!')
@app.listener('after_server_stop')
async def close_db(app, loop):
await app.db.close()
还可以使用register_listener方法注册侦听器。如果您在实例化应用程序的模块之外的另一个模块中定义侦听器,这可能会很有用。
app = Sanic()
async def setup_db(app, loop):
app.db = await db_setup()
app.register_listener(setup_db, 'before_server_start')
如果您希望在循环启动后调度一个后台任务来运行,Sanic提供了add_task方法来轻松完成。
async def notify_server_started_after_five_seconds():
await asyncio.sleep(5)
print('Server successfully started!')
app.add_task(notify_server_started_after_five_seconds())
Sanic提供自动注入应用,
async def notify_server_started_after_five_seconds(app):
await asyncio.sleep(5)
print(app.name)
app.add_task(notify_server_started_after_five_seconds)
可以使用一下代码实现:
async def notify_server_started_after_five_seconds(app):
await asyncio.sleep(5)
print(app.name)
app.add_task(notify_server_started_after_five_seconds(app))