refactor(core): 平台上报收敛为单个请求头
去掉 device_info_plus 依赖与机型/系统版本,只保留 X-Client-Platform。
This commit is contained in:
1 parent
01a3b0101e
commit
935de13343
6 files changed
+19
-113
No files matched your search
@@ -5,7 +5,6 @@ import 'package:dio/dio.dart';
|
||||
import '../../config/app_config.dart';
|
||||
import 'api_exception.dart';
|
||||
import 'api_interceptors.dart';
|
||||
import 'device_profile.dart';
|
||||
import 'network_log_interceptor.dart';
|
||||
|
||||
/// `ApiException` 从这里也能拿到:历史调用方一律 `import 'api_client.dart'`,不必改 import。
|
||||
@@ -25,7 +24,7 @@ class ApiClient {
|
||||
this.tokenRefresher,
|
||||
this.onUnauthorized,
|
||||
this.deviceIdReader,
|
||||
this.deviceProfileReader,
|
||||
this.platformReader,
|
||||
}) : _fixedBaseUrl = baseUrl {
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
@@ -42,7 +41,7 @@ class ApiClient {
|
||||
AuthHeaderInterceptor(
|
||||
accessTokenReader: accessTokenReader,
|
||||
deviceIdReader: deviceIdReader,
|
||||
deviceProfileReader: deviceProfileReader,
|
||||
platformReader: platformReader,
|
||||
),
|
||||
const EnvelopeInterceptor(),
|
||||
NetworkLogInterceptor(),
|
||||
@@ -70,8 +69,8 @@ class ApiClient {
|
||||
/// 设备号(`X-Device-Id`):注册风控、后续下载绑定都要用
|
||||
final Future<String> Function()? deviceIdReader;
|
||||
|
||||
/// 设备画像(系统/机型版本):后台列表展示客户端系统用
|
||||
final Future<DeviceProfile> Function()? deviceProfileReader;
|
||||
/// 客户端平台(`X-Client-Platform`):后台区分 iOS / Android
|
||||
final String Function()? platformReader;
|
||||
|
||||
Future<Object?> get(String path, {Map<String, String>? query}) {
|
||||
return _request('GET', path, query: query);
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'dart:convert';
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import 'api_exception.dart';
|
||||
import 'device_profile.dart';
|
||||
import 'network_log_interceptor.dart';
|
||||
|
||||
/// 请求级开关:放在 `RequestOptions.extra` 里,由 `ApiClient` 写入、拦截器读取。
|
||||
@@ -36,7 +35,7 @@ class AuthHeaderInterceptor extends Interceptor {
|
||||
AuthHeaderInterceptor({
|
||||
this.accessTokenReader,
|
||||
this.deviceIdReader,
|
||||
this.deviceProfileReader,
|
||||
this.platformReader,
|
||||
});
|
||||
|
||||
/// 当前 access token;未登录返回 null 或空串。
|
||||
@@ -45,8 +44,8 @@ class AuthHeaderInterceptor extends Interceptor {
|
||||
/// 设备号(`X-Device-Id`):注册风控、下载绑定都用它。
|
||||
final Future<String> Function()? deviceIdReader;
|
||||
|
||||
/// 设备画像(系统/机型):后台判断客户端系统用,匿名请求同样要带。
|
||||
final Future<DeviceProfile> Function()? deviceProfileReader;
|
||||
/// 客户端平台(`X-Client-Platform`):后台区分 iOS / Android,匿名请求同样要带。
|
||||
final String Function()? platformReader;
|
||||
|
||||
@override
|
||||
Future<void> onRequest(
|
||||
@@ -62,9 +61,9 @@ class AuthHeaderInterceptor extends Interceptor {
|
||||
if (deviceId != null && deviceId.isNotEmpty) {
|
||||
options.headers['X-Device-Id'] = deviceId;
|
||||
}
|
||||
final profile = await deviceProfileReader?.call();
|
||||
if (profile != null) {
|
||||
options.headers.addAll(profile.headers);
|
||||
final platform = platformReader?.call() ?? '';
|
||||
if (platform.isNotEmpty) {
|
||||
options.headers['X-Client-Platform'] = platform;
|
||||
}
|
||||
handler.next(options);
|
||||
}
|
||||
|
||||
@@ -2,68 +2,14 @@
|
||||
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
/// 设备画像:随每个请求以请求头上报,供后台列表识别客户端系统。
|
||||
/// 客户端平台,后台只用来区分 iOS / Android。
|
||||
///
|
||||
/// 之前只有登录接口在 body 里带 `platform` / `osVersion`,匿名互动没有任何系统信息,
|
||||
/// 后台只能显示「—」。改成请求头后,点赞、收藏、评论、观看等接口都能带上。
|
||||
class DeviceProfile {
|
||||
const DeviceProfile({
|
||||
this.platform = '',
|
||||
this.osVersion = '',
|
||||
this.model = '',
|
||||
});
|
||||
|
||||
/// ANDROID / IOS / WEB;桌面端等无法归类时为空。
|
||||
final String platform;
|
||||
|
||||
/// 系统版本,Android 取 release(如 14),iOS 取 systemVersion(如 17.2)。
|
||||
final String osVersion;
|
||||
|
||||
/// 机型,Android 取 model(如 SM-G991B),iOS 取 utsname.machine(如 iPhone15,2)。
|
||||
final String model;
|
||||
|
||||
Map<String, String> get headers => {
|
||||
if (platform.isNotEmpty) 'X-Client-Platform': platform,
|
||||
if (osVersion.isNotEmpty) 'X-Client-Os': osVersion,
|
||||
if (model.isNotEmpty) 'X-Client-Model': model,
|
||||
};
|
||||
}
|
||||
|
||||
/// 读取一次并缓存设备画像:插件调用有开销,且整个进程内不会变。
|
||||
class DeviceProfileReader {
|
||||
DeviceProfileReader({DeviceInfoPlugin? plugin})
|
||||
: _plugin = plugin ?? DeviceInfoPlugin();
|
||||
|
||||
final DeviceInfoPlugin _plugin;
|
||||
Future<DeviceProfile>? _cached;
|
||||
|
||||
Future<DeviceProfile> read() => _cached ??= _load();
|
||||
|
||||
Future<DeviceProfile> _load() async {
|
||||
if (kIsWeb) return const DeviceProfile(platform: 'WEB');
|
||||
try {
|
||||
if (Platform.isAndroid) {
|
||||
final info = await _plugin.androidInfo;
|
||||
return DeviceProfile(
|
||||
platform: 'ANDROID',
|
||||
osVersion: info.version.release,
|
||||
model: info.model,
|
||||
);
|
||||
}
|
||||
if (Platform.isIOS) {
|
||||
final info = await _plugin.iosInfo;
|
||||
return DeviceProfile(
|
||||
platform: 'IOS',
|
||||
osVersion: info.systemVersion,
|
||||
model: info.utsname.machine,
|
||||
);
|
||||
}
|
||||
} catch (_) {
|
||||
// 插件不可用(widget 测试没有原生通道)时退化为 dart:io 能拿到的信息
|
||||
}
|
||||
return const DeviceProfile();
|
||||
}
|
||||
/// 系统版本、机型一律不上报:后台列表需要的只是「这台设备是安卓还是苹果」。
|
||||
String clientPlatform() {
|
||||
if (kIsWeb) return 'WEB';
|
||||
if (Platform.isAndroid) return 'ANDROID';
|
||||
if (Platform.isIOS) return 'IOS';
|
||||
return '';
|
||||
}
|
||||
Reference in new issue
Block a user