首先在Sanic的生命周期,流程大致如下:
http请求——Sanic解析request——匹配路由——请求中间件——视图函数——响应中间件——http响应
Sanic在匹配路由中会检测是否存在对应的请求方法,如果没有直接响应405,根本不走后面的中间件了,这意味着你不能使用中间件来实现所有路由表上的预检请求,那么在注册路由的时候,就一定要显式申明OPTIONS或在CBV中实现options方法,之后我们才可以通过中间件来实现功能
@app.middleware("request")
def cors_middle_req(request: Request):
"""路由需要启用OPTIONS方法"""
if request.method.lower() == 'options':
allow_headers = [
'Authorization',
'content-type'
]
headers = {
'Access-Control-Allow-Methods':
', '.join(request.app.router.get_supported_methods(request.path)),
'Access-Control-Max-Age': '86400',
'Access-Control-Allow-Headers': ', '.join(allow_headers),
}
return HTTPResponse('', headers=headers)
@app.middleware("response")
def cors_middle_res(request: Request, response: HTTPResponse):
"""跨域处理"""
allow_origin = '*'
response.headers.update(
{
'Access-Control-Allow-Origin': allow_origin,
}
)
前一个请求中间件cors_middle_req用于拦截所有OPTIONS方法,它在设置三个跨域请求头后直接返回HTTPResponse对象,在这个中间件中,告知了浏览器允许的请求方式和请求头,并设置了一个24小时的缓存(86400/3600)时间
后一个响应中间件cors_middle_res用于处理所有响应请求,在响应头中加入Access-Control-Allow-Origin来允许跨域,allow_origin可以改成指定域名
在整个过程中我们使用到了6个规范响应头中最常用的4个,剩下两个响应头大家可以自行去了解用途和适用场景