使用Connexion+Flask时after_request打印响应致Swagger-UI异常的咨询
问题:Connexion+Swagger-UI响应日志导致界面功能异常
环境配置
- connexion[swagger-ui]==2.13.0
- Flask==2.2.5
需求与实现
使用Connexion搭建应用并托管Swagger-UI,需要在请求处理前后打印所有请求和响应的payload到控制台。
构建Connexion应用后添加了以下代码:
# Add pre payload printer to app connex_app.app.before_request(print_request(config)) connex_app.app.after_request(print_response(config))
对应的日志函数实现:
def print_request(config): ''' Print out requests received, or response sent ''' def request_logger(): if request.method not in ('GET'): if config.myproject.logging.myproject.pretty_print.request_payloads: logger.debug(f"Request received, Body: {request.get_data(as_text=True)}") else: data = request.get_json() if request.is_json else {} flat_json = json.dumps(data, separators=(',', ':')) logger.debug(f"Request received, Body: {flat_json}") else: logger.debug("Request received") return request_logger def print_response(config): ''' Print out requests received, or response sent ''' def response_logger(response): # Ensure you have access to the correct response object here, this might need to be passed explicitly if config.myproject.logging.myproject.pretty_print.response_payloads: logger.debug(f"Response sent, Body: {response.get_data(as_text=False)}") else: # This section might need adjustment based on how you're handling response data data = response.get_json() if response.is_json else {} flat_json = json.dumps(data, separators=(',', ':')) logger.debug(f"Response sent, Body: {flat_json}") return response return response_logger
问题点
执行response.get_data(as_text=False)这行代码时,会导致Swagger-UI的请求和响应被异常重定向,直接破坏Swagger-UI的正常功能。此前使用旧版Connexion 2.x时无此问题,但当前因依赖限制无法升级到3.0,且必须固定使用Flask==2.2.5。
解决方案
1. 修复get_data的调用方式
response.get_data(as_text=False)返回字节流,打印时可能干扰Flask对响应内容的后续处理(比如Swagger-UI的静态资源、HTML内容)。将参数改为as_text=True,统一以文本形式获取响应内容:
logger.debug(f"Response sent, Body: {response.get_data(as_text=True)}")
这样可以避免字节流读取导致的响应对象状态异常,同时不影响日志内容的可读性。
2. 过滤Swagger-UI相关请求
如果不需要打印Swagger-UI自身的请求(比如静态资源、界面请求),可以在日志函数中添加路径过滤,跳过这些请求的日志打印:
def response_logger(response): # 跳过Swagger-UI相关路径的日志 if request.path.startswith('/swagger/') or request.path == '/swagger.json': return response # 原日志逻辑 if config.myproject.logging.myproject.pretty_print.response_payloads: logger.debug(f"Response sent, Body: {response.get_data(as_text=True)}") else: data = response.get_json() if response.is_json else {} flat_json = json.dumps(data, separators=(',', ':')) logger.debug(f"Response sent, Body: {flat_json}") return response
同样在request_logger中也可以添加相同的路径过滤规则,减少无关日志。
3. 优化非JSON响应的处理逻辑
对于Swagger-UI返回的HTML、CSS等非JSON响应,response.get_json()会返回None,此时无需强行JSON序列化,直接打印原始文本即可:
else: if response.is_json: data = response.get_json() flat_json = json.dumps(data, separators=(',', ':')) logger.debug(f"Response sent, Body: {flat_json}") else: # 非JSON响应直接打印文本内容 logger.debug(f"Response sent, Body: {response.get_data(as_text=True)}")
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

