更新
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:new_learn/core/logger/app_talker.dart';
|
||||
@@ -53,6 +55,10 @@ class DioClient {
|
||||
),
|
||||
) {
|
||||
if (enableNetworkLog) {
|
||||
// 必须在 Talker 之前:把二进制 body 临时换成占位文本,
|
||||
// 防止 Talker 把整张图(上百万字节)转成巨型日志字符串导致 OOM。
|
||||
// 真实字节存在 extra 里,由 _buildInterceptors 的 onRequest 还原。
|
||||
_dio.interceptors.add(_BinaryLogMaskInterceptor());
|
||||
_dio.interceptors.add(
|
||||
TalkerDioLogger(
|
||||
talker: talker,
|
||||
@@ -88,6 +94,11 @@ class DioClient {
|
||||
return InterceptorsWrapper(
|
||||
// ① 请求发出前:加 Token + 打印日志
|
||||
onRequest: (options, handler) {
|
||||
// 还原被 _BinaryLogMaskInterceptor 临时替换的二进制 body,保证实际上传内容不变
|
||||
final realBody = options.extra.remove(_kRealBodyKey);
|
||||
if (realBody != null) {
|
||||
options.data = realBody;
|
||||
}
|
||||
// OSS 直传会带自己的 authorization 头(OSS4-HMAC-SHA256 签名),
|
||||
// 任何形式存在 authorization 都不再加 Bearer,否则会覆盖 OSS 签名
|
||||
final hasAuth =
|
||||
@@ -177,16 +188,20 @@ class DioClient {
|
||||
ProgressCallback? onReceiveProgress,
|
||||
int retries = 0,
|
||||
Map<String, dynamic>? headers,
|
||||
Duration? receiveTimeout,
|
||||
}) async {
|
||||
var attempt = 0;
|
||||
while (true) {
|
||||
try {
|
||||
final options = (headers != null || receiveTimeout != null)
|
||||
? Options(headers: headers, receiveTimeout: receiveTimeout)
|
||||
: null;
|
||||
final resp = await _dio.get<dynamic>(
|
||||
path,
|
||||
queryParameters: query,
|
||||
cancelToken: cancelToken,
|
||||
onReceiveProgress: onReceiveProgress,
|
||||
options: headers == null ? null : Options(headers: headers),
|
||||
options: options,
|
||||
);
|
||||
return resp.data;
|
||||
} on DioException catch (e) {
|
||||
@@ -337,3 +352,25 @@ class ApiException implements Exception {
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
|
||||
/// extra 中暂存真实二进制 body 的 key
|
||||
const String _kRealBodyKey = '_realBinaryBody@dio';
|
||||
|
||||
/// 二进制日志屏蔽拦截器(必须在 TalkerDioLogger 之前执行):
|
||||
/// 把二进制 body 暂存到 extra 并替换成简短占位文本,
|
||||
/// 避免 Talker 把整张图转成巨型日志字符串、堆积在日志历史里造成 OOM。
|
||||
/// 真实字节由 _buildInterceptors 的 onRequest 还原,不影响实际请求内容。
|
||||
class _BinaryLogMaskInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
final data = options.data;
|
||||
if (data is TypedData) {
|
||||
options.extra[_kRealBodyKey] = data;
|
||||
options.data = '<binary ${data.lengthInBytes} bytes>';
|
||||
} else if (data is Stream<List<int>>) {
|
||||
options.extra[_kRealBodyKey] = data;
|
||||
options.data = '<binary stream>';
|
||||
}
|
||||
handler.next(options);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user