如何在Flutter中通过LogInterceptor单次打印完整请求体?
解决Dio LogInterceptor单次打印完整请求体的问题
你的代码存在两个核心问题:
- 日志碎片化输出:
LogInterceptor会把请求的不同部分(请求头、请求体、响应等)拆分成多次调用logPrint,而你每次回调都立刻打印StringBuffer,导致输出的是逐步构建的日志片段,而非完整请求内容。 - 异步时机问题:在
dio.interceptors.add()外部打印logObject时,logPrint回调还未执行(请求是异步发起的),所以此时logObject是空的。
方案一:自定义拦截器直接打印完整请求/响应
这种方式更直接,无需依赖LogInterceptor的碎片化日志,直接在请求生命周期中获取完整内容单次打印:
if (kDebugMode) { dio.interceptors.add( InterceptorsWrapper( // 处理请求前打印完整请求信息 onRequest: (options, handler) { String requestBody = options.data != null ? (options.data is Map ? jsonEncode(options.data) : options.data.toString()) : '无请求体'; final fullRequestLog = """ === 请求开始 === URL: ${options.uri} 方法: ${options.method} 请求头: ${jsonEncode(options.headers)} 请求体: $requestBody === 请求结束 === """; djLogger.debug(content: "完整请求日志:", value: fullRequestLog); handler.next(options); }, // 可选:打印完整响应信息 onResponse: (response, handler) { String responseBody = response.data != null ? (response.data is Map ? jsonEncode(response.data) : response.data.toString()) : '无响应体'; final fullResponseLog = """ === 响应开始 === 状态码: ${response.statusCode} 响应头: ${jsonEncode(response.headers.map)} 响应体: $responseBody === 响应结束 === """; djLogger.debug(content: "完整响应日志:", value: fullResponseLog); handler.next(response); }, // 可选:打印请求错误信息 onError: (DioException e, handler) { String errorRequestBody = e.requestOptions.data != null ? (e.requestOptions.data is Map ? jsonEncode(e.requestOptions.data) : e.requestOptions.data.toString()) : '无请求体'; final errorLog = """ === 请求错误 === 错误信息: ${e.message} 请求URL: ${e.requestOptions.uri} 请求体: $errorRequestBody === 错误结束 === """; djLogger.debug(content: "请求错误日志:", value: errorLog); handler.next(e); }, ), ); }
方案二:修改LogInterceptor的日志收集逻辑
如果你想继续使用LogInterceptor,可以通过判断日志结束标记,收集完所有片段后单次打印:
if (kDebugMode) { // 每个请求对应一个独立的StringBuffer,避免并发请求日志混乱 final requestLogBuffers = <int, StringBuffer>{}; dio.interceptors.add( LogInterceptor( requestBody: true, responseBody: true, requestHeader: true, responseHeader: true, error: true, logPrint: (Object object) { // 获取当前请求的id,用于关联日志片段 final requestId = int.tryParse(object.toString().split(' ').first) ?? 0; if (!requestLogBuffers.containsKey(requestId)) { requestLogBuffers[requestId] = StringBuffer(); } final buffer = requestLogBuffers[requestId]!; buffer.writeln(object); // 判断是否为当前请求的最后一条日志(LogInterceptor默认会输出"END HTTP"结尾) if (object.toString().contains("END HTTP")) { djLogger.debug(content: "完整请求/响应日志:", value: buffer.toString()); // 打印后移除buffer,避免内存占用 requestLogBuffers.remove(requestId); } }, ), ); }
内容的提问来源于stack exchange,提问作者Luiz Fiuza
相关产品推荐
相关产品推荐

