十、中间件(用处不大)

1、Flask中间件

  Flask的中间件与django的不太一样,反而Flask的before_request和after_request这两个装饰器的功能跟django中间件很像,所以如果想实现在请求到达视图函数之前的操作和处理响应的操作,可以使用这两个装饰器实现。Flask中间件所处的位置比较早,处于还没有生成请求(from flask import request)的阶段,面向的是environ(原始的请求),所以作用有限。

environ是一个字典,里面是被初步解析的请求信息

{'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', 'wsgi.input': <_io.BufferedReader name=1000>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'werkzeug.server.shutdown': <function WSGIRequestHandler.make_environ.<locals>.shutdown_server at 0x041C82B8>, 'SERVER_SOFTWARE': 'Werkzeug/0.16.0', 'REQUEST_METHOD': 'GET', 'SCRIPT_NAME': '', 'PATH_INFO': '/', 'QUERY_STRING': '', 'REQUEST_URI': '/', 'RAW_URI': '/', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': 60113, 'SERVER_NAME': '127.0.0.1', 'SERVER_PORT': '80', 'SERVER_PROTOCOL': 'HTTP/1.1', 'HTTP_HOST': 'localhost', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_CACHE_CONTROL': 'max-age=0', 'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36', 'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', 'HTTP_SEC_FETCH_SITE': 'none', 'HTTP_SEC_FETCH_MODE': 'navigate', 'HTTP_SEC_FETCH_USER': '?1', 'HTTP_SEC_FETCH_DEST': 'document', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9,en;q=0.8', 'HTTP_COOKIE': 'Pycharm-18abade8=5c2f01d3-4c8d-4198-b783-a7285b110947; Pycharm-f4457c6=1e12264a-74c9-43cb-8c90-ddd1398baef7', 'werkzeug.request': <BaseRequest 'http://localhost/' [GET]>}

所以,如果想要做一些简单的功能(请求拦截、IP访问控制等操作),可以实现,但是使用before_request和after_request这两个装饰器一样可以,所以其最用有限。

2、中间件的使用

 1 from flask import Flask, Response
 2 
 3 
 4 app = Flask(__name__)
 5 
 6 
 7 @app.route("/")
 8 def index():
 9     return "Hello, index"
10 
11 
12 class Middleware:
13     def __init__(self, wsgi_app):
14         self.old_wsgi_app = wsgi_app
15 
16     def __call__(self, environ, start_response):
17         print(environ.get("REMOTE_ADDR"))
18 
19         print(start_response)
20         res = self.old_wsgi_app(environ, start_response)
21         print(type(res))  # <class 'werkzeug.wsgi.ClosingIterator'>
22         return res
23 
24 
25 if __name__ == '__main__':
26     app.wsgi_app = Middleware(app.wsgi_app)
27     app.run("localhost", 80, debug=True)

我们可以自定制一个中间件类,res = self.old_wsgi_app(environ, start_response) 和 return res 不能修改,__call__方法中的其他地方就是我们实现自己功能的地方。至于为什么这样可以实现,就与前面随笔中对请求上下文中的源码分析有关了。

原文地址:https://www.cnblogs.com/loveprogramme/p/13381620.html