具有请求和响应的 Flask 中间件
Flask Middleware with both Request and Response
我想在 Flask 中创建一个中间件功能,用于记录请求 和 响应的详细信息。中间件应该 运行 在 Response 被创建之后,但在它被发回之前。我要登录:
- 请求的 HTTP 方法(
GET
、POST
或 PUT
)
- 请求端点
- 响应 HTTP 状态代码,包括 500 个响应。因此,如果在视图函数中引发异常,我想在 Flask 内部发送它之前记录生成的 500 响应。
我发现的一些选项(对我来说不太适用):
before_request
and after_request
装饰器。如果我可以访问 after_request
中的请求数据,我的问题仍然无法解决,因为根据文档
If a function raises an exception, any remaining after_request
functions will not be called.
本页描述的- Deferred Request Callbacks - there is an
after_this_request
装饰器,装饰任意一个函数(定义在当前视图函数内部),并在当前请求后注册到运行。由于任意函数可以包含来自请求和响应的信息,因此它部分解决了我的问题。问题是我必须向每个视图函数添加这样一个装饰函数;我非常想避免这种情况。
@app.route('/')
def index():
@after_this_request
def add_header(response):
response.headers['X-Foo'] = 'Parachute'
return response
return 'Hello World!'
有什么建议吗?
好吧,在 Deferred Request Callbacks 的页面上,答案一直盯着我看。
诀窍是在当前请求之后使用 after_this_request
从 before_request
回调 中向 运行 注册一个函数。这是对我有用的代码片段:
@app.before_request
def log_details():
method = request.method
url = request.url
@after_this_request
def log_details_callback(response: Response):
logger.info(f'method: {method}\n url: {url}\n status: {response.status}')
这些是步骤:
- 从
before_request
回调中的响应中获取所需的详细信息,并将它们存储在一些变量中。
- 然后在您用
after_this_request
装饰的函数中访问您想要的响应,以及您之前存储请求详细信息的变量。
我的第一个回答很老套。实际上有一种更好的方法可以通过使用 g object
in Flask. It is useful for storing information globally during a single request. From the documentation:
来实现相同的结果
The g name stands for “global”, but that is referring to the data being global within a context. The data on g is lost after the context ends, and it is not an appropriate place to store data between requests. Use the session or a database to store data across requests.
你会这样使用它:
@app.before_request
def gather_request_data():
g.method = request.method
g.url = request.url
@app.after_request
def log_details(response: Response):
g.status = response.status
logger.info(f'method: {g.method}\n url: {g.url}\n status: {g.status}')
return response
- 在用
@app.before_request
装饰的函数中收集您想要的任何请求信息,并将其存储在 g
对象中。
- 从装饰有
@app.after_request
的函数中的响应中访问任何你想要的。您仍然可以参考步骤 1 中存储在 g
对象中的信息。请注意,您必须 return 此函数末尾的响应。
你可以使用 flask-http-middleware
link
from flask import Flask
from flask_http_middleware import MiddlewareManager, BaseHTTPMiddleware
app = Flask(__name__)
class MetricsMiddleware(BaseHTTPMiddleware):
def __init__(self):
super().__init__()
def dispatch(self, request, call_next):
url = request.url
response = call_next(request)
response.headers.add("x-url", url)
return response
app.wsgi_app = MiddlewareManager(app)
app.wsgi_app.add_middleware(MetricsMiddleware)
@app.get("/health")
def health():
return {"message":"I'm healthy"}
if __name__ == "__main__":
app.run()
每次请求都会通过中间件
我想在 Flask 中创建一个中间件功能,用于记录请求 和 响应的详细信息。中间件应该 运行 在 Response 被创建之后,但在它被发回之前。我要登录:
- 请求的 HTTP 方法(
GET
、POST
或PUT
) - 请求端点
- 响应 HTTP 状态代码,包括 500 个响应。因此,如果在视图函数中引发异常,我想在 Flask 内部发送它之前记录生成的 500 响应。
我发现的一些选项(对我来说不太适用):
before_request
andafter_request
装饰器。如果我可以访问after_request
中的请求数据,我的问题仍然无法解决,因为根据文档
If a function raises an exception, any remaining
after_request
functions will not be called.
-
本页描述的
- Deferred Request Callbacks - there is an
after_this_request
装饰器,装饰任意一个函数(定义在当前视图函数内部),并在当前请求后注册到运行。由于任意函数可以包含来自请求和响应的信息,因此它部分解决了我的问题。问题是我必须向每个视图函数添加这样一个装饰函数;我非常想避免这种情况。
@app.route('/') def index(): @after_this_request def add_header(response): response.headers['X-Foo'] = 'Parachute' return response return 'Hello World!'
有什么建议吗?
好吧,在 Deferred Request Callbacks 的页面上,答案一直盯着我看。
诀窍是在当前请求之后使用 after_this_request
从 before_request
回调 中向 运行 注册一个函数。这是对我有用的代码片段:
@app.before_request
def log_details():
method = request.method
url = request.url
@after_this_request
def log_details_callback(response: Response):
logger.info(f'method: {method}\n url: {url}\n status: {response.status}')
这些是步骤:
- 从
before_request
回调中的响应中获取所需的详细信息,并将它们存储在一些变量中。 - 然后在您用
after_this_request
装饰的函数中访问您想要的响应,以及您之前存储请求详细信息的变量。
我的第一个回答很老套。实际上有一种更好的方法可以通过使用 g object
in Flask. It is useful for storing information globally during a single request. From the documentation:
The g name stands for “global”, but that is referring to the data being global within a context. The data on g is lost after the context ends, and it is not an appropriate place to store data between requests. Use the session or a database to store data across requests.
你会这样使用它:
@app.before_request
def gather_request_data():
g.method = request.method
g.url = request.url
@app.after_request
def log_details(response: Response):
g.status = response.status
logger.info(f'method: {g.method}\n url: {g.url}\n status: {g.status}')
return response
- 在用
@app.before_request
装饰的函数中收集您想要的任何请求信息,并将其存储在g
对象中。 - 从装饰有
@app.after_request
的函数中的响应中访问任何你想要的。您仍然可以参考步骤 1 中存储在g
对象中的信息。请注意,您必须 return 此函数末尾的响应。
你可以使用 flask-http-middleware
link
from flask import Flask
from flask_http_middleware import MiddlewareManager, BaseHTTPMiddleware
app = Flask(__name__)
class MetricsMiddleware(BaseHTTPMiddleware):
def __init__(self):
super().__init__()
def dispatch(self, request, call_next):
url = request.url
response = call_next(request)
response.headers.add("x-url", url)
return response
app.wsgi_app = MiddlewareManager(app)
app.wsgi_app.add_middleware(MetricsMiddleware)
@app.get("/health")
def health():
return {"message":"I'm healthy"}
if __name__ == "__main__":
app.run()
每次请求都会通过中间件