Flask API自动获取端点实现日志白名单失效问题排查
问题原因及解决方案
核心问题:混淆了端点名称与URL路径规则
你手动指定permitted时能正常工作,是因为你写的字符串刚好和URL路径的最后一段同名(比如端点hello对应URL/api/v1/hello),正则/api/v1/{endpoint}.*能匹配到实际请求路径。
但通过app.url_map.iter_rules()获取的rule.endpoint是视图函数的名称(比如getEvidences),而对应的URL路径可能是/api/v1/evidences(而非/api/v1/getEvidences),这时候正则完全匹配不上实际请求路径,自然不会生成日志。
修正方案
方案1:基于URL路径规则匹配(推荐)
直接使用路由的URL规则来构建正则匹配模式,同时处理动态参数:
import re from flask import serving def restrict_access_logs(): parent_log_request = serving.WSGIRequestHandler.log_request permitted_patterns = [] # 遍历所有路由,筛选/api/v1前缀的规则并转换为正则 for rule in app.url_map.iter_rules(): if rule.rule.startswith('/api/v1/'): # 将路由中的动态参数(如<product_id>)替换为正则通配符 regex_pattern = re.sub(r'<[^>]+>', r'[^/]+', rule.rule) # 用^开头确保匹配路径前缀,避免垃圾请求的路径包含合法前缀但位置不对 permitted_patterns.append(f"^{regex_pattern}") def log_request(self, *args, **kwargs): if any(re.match(pattern, self.path) for pattern in permitted_patterns): parent_log_request(self, *args, **kwargs) serving.WSGIRequestHandler.log_request = log_request
方案2:基于端点名称匹配(需映射关系)
如果一定要通过端点名称控制,需要先建立端点到URL规则的映射,再解析请求对应的端点:
from flask import serving, request def restrict_access_logs(): parent_log_request = serving.WSGIRequestHandler.log_request # 获取所有端点名称 permitted_endpoints = [rule.endpoint for rule in app.url_map.iter_rules()] def log_request(self, *args, **kwargs): # 解析当前请求对应的端点 adapter = app.url_map.bind('localhost') try: endpoint, _ = adapter.match(request.path) if endpoint in permitted_endpoints: parent_log_request(self, *args, **kwargs) except: # 匹配失败的请求直接跳过日志 pass serving.WSGIRequestHandler.log_request = log_request
额外注意事项
- 确保
restrict_access_logs在所有路由注册完成后调用,否则会漏掉部分路由规则; - 方案1中可以根据需求调整正则的匹配逻辑(比如是否允许路径后缀等)。
内容的提问来源于stack exchange,提问作者HumanzIzDead
相关产品推荐
相关产品推荐

