You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中通过LogInterceptor单次打印完整请求体?

解决Dio LogInterceptor单次打印完整请求体的问题

你的代码存在两个核心问题:

  1. 日志碎片化输出:LogInterceptor会把请求的不同部分(请求头、请求体、响应等)拆分成多次调用logPrint,而你每次回调都立刻打印StringBuffer,导致输出的是逐步构建的日志片段,而非完整请求内容。
  2. 异步时机问题:在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 00:52:22