[flask]中心件

打印 上一主题 下一主题

主题 1764|帖子 1764|积分 5292

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
前言

中心件用于在哀求到达视图函数之前或响应返回给客户端之前执行一些操作,比如身份验证、日志记录、错误处理等。
方式1,使用钩子函数
  1. from flask import Flask, request, Response
  2. def DemoMiddleWare(app: Flask):
  3.     @app.before_request
  4.     def before_request1():
  5.         print("before_request")
  6.     @app.after_request
  7.     def after_request1(response: Response):
  8.         print(f"after_request, method: {request.method}, path: {request.path}")
  9.         return response
  10.    
  11.     return app
  12. app = Flask(__name__)
  13. @app.get("/")
  14. def hello():
  15.     return "Hello World!"
  16. app = DemoMiddleWare(app)
  17. if __name__ == "__main__":
  18.     app.run(debug=False)
复制代码
方式2,实现中心件类
  1. from flask import Flask
  2. from werkzeug.middleware.proxy_fix import ProxyFix
  3. import time
  4. class MyMiddleWare:
  5.     def __init__(self, app):
  6.         self.app = app
  7.     def __call__(self, environ, start_response):
  8.         data = {
  9.             "method": environ.get("REQUEST_METHOD", "NaN"),
  10.             "scheme": environ.get("wsgi.url_scheme", "NaN"),
  11.             "server_protocol": environ.get("SERVER_PROTOCOL", "NaN"),
  12.             "remote_addr": environ.get("REMOTE_ADDR", "NaN"),
  13.             "host": environ.get("HTTP_HOST", "NaN"),
  14.             "path": environ.get("PATH_INFO", "NaN"),
  15.             "user_agent": environ.get("HTTP_USER_AGENT", "NaN"),
  16.         }
  17.         # 自定义请求头都以 HTTP_* 开头
  18.         if header_ha := environ.get("HTTP_HA", ""):
  19.             data["header_ha"] = header_ha
  20.         # 处理 cookie
  21.         if cookie := environ.get("HTTP_COOKIE", ""):
  22.             data["cookie"] = cookie
  23.         start_time = time.time()
  24.         response = self.app(environ, start_response)
  25.         data["response_time"] = round((time.time() - start_time), 4)
  26.         print(data)
  27.         return response
  28. class My2MiddleWare:
  29.     def __init__(self, app):
  30.         self.app = app
  31.     def __call__(self, environ, start_response):
  32.         print("This is middleware2, before request")
  33.         response = self.app(environ, start_response)
  34.         print("This is middleware2, after request")
  35.         return response
  36. app = Flask(__name__)
  37. # ProxyFix是werkzeug提供的一个中间件,当flask应用部署在反向代理器后面时,可以将反向代理器设置得X-Forwarded-*头信息
  38. # 具体ProxyFix处理了哪些代理请求头可以参考ProxyFix的docstring
  39. app.wsgi_app = ProxyFix(app.wsgi_app)
  40. app.wsgi_app = MyMiddleWare(app.wsgi_app)
  41. app.wsgi_app = My2MiddleWare(app.wsgi_app)  # 添加第2个中间件
  42. @app.get("/")
  43. def hello():
  44.     return "Hello World!"
  45. @app.get("/2")
  46. def hello2():
  47.     return "Hello World!"
  48. if __name__ == "__main__":
  49.     app.run(debug=False)
复制代码
上面示例代码只处理了哀求头等信息,偶然候可能还需要处理响应,比如获取响应码、设置响应头等。
  1. from flask import Flask
  2. import time
  3. class MyMiddleWare:
  4.     def __init__(self, app):
  5.         self.app = app
  6.     def __call__(self, environ, start_response):
  7.         data = {
  8.             "method": environ.get("REQUEST_METHOD", "NaN"),
  9.             "scheme": environ.get("wsgi.url_scheme", "NaN"),
  10.             "server_protocol": environ.get("SERVER_PROTOCOL", "NaN"),
  11.             "remote_addr": environ.get("REMOTE_ADDR", "NaN"),
  12.             "host": environ.get("HTTP_HOST", "NaN"),
  13.             "path": environ.get("PATH_INFO", "NaN"),
  14.             "user_agent": environ.get("HTTP_USER_AGENT", "NaN"),
  15.         }
  16.         # 自定义请求头都以 HTTP_* 开头
  17.         if header_ha := environ.get("HTTP_HA", ""):
  18.             data["header_ha"] = header_ha
  19.         # 处理 cookie
  20.         if cookie := environ.get("HTTP_COOKIE", ""):
  21.             data["cookie"] = cookie
  22.         resp_status_code = None
  23.         resp_headers = []
  24.         def catching_start_response(status, headers, exc_info=None):
  25.             nonlocal resp_status_code, resp_headers
  26.             resp_status_code = status
  27.             headers.append(("X-Resp1", "OK"))  # 添加自定义响应头
  28.             resp_headers = headers
  29.             return start_response(status, headers, exc_info)
  30.         start_time = time.time()
  31.         response = self.app(environ, catching_start_response)
  32.         data["status"] = resp_status_code
  33.         data["response_time"] = round((time.time() - start_time), 4)
  34.         print(data)
  35.         print(f"response headers: {resp_headers}")
  36.         return response
  37. app = Flask(__name__)
  38. app.wsgi_app = MyMiddleWare(app.wsgi_app)
  39. @app.get("/")
  40. def hello():
  41.     return "Hello World!"
  42. @app.get("/2")
  43. def hello2():
  44.     return "Hello World!"
  45. if __name__ == "__main__":
  46.     app.run(debug=False)
复制代码
小结

两种方式实现中心件都行,不外用钩子函数会更方便点。假如想水代码行数,用中心件类也是不错的选择。
参考


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

卖不甜枣

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表