mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
enable http2 (#331)
This commit is contained in:
committed by
GitHub
parent
1c3d77b95d
commit
0a6950e34a
@@ -23,8 +23,8 @@ class Constants {
|
|||||||
static const String userAgent =
|
static const String userAgent =
|
||||||
'Mozilla/5.0 BiliDroid/1.46.2 (bbcallen@gmail.com) os/android model/vivo mobi_app/android_hd build/2001100 channel/yingyongbao innerVer/2001100 osVer/14 network/2';
|
'Mozilla/5.0 BiliDroid/1.46.2 (bbcallen@gmail.com) os/android model/vivo mobi_app/android_hd build/2001100 channel/yingyongbao innerVer/2001100 osVer/14 network/2';
|
||||||
static const String statistics =
|
static const String statistics =
|
||||||
'%7B%22appId%22%3A5%2C%22platform%22%3A3%2C%22version%22%3A%221.46.2%22%2C%22abtest%22%3A%22%22%7D';
|
'{"appId":5,"platform":3,"version":"1.46.2","abtest":""}';
|
||||||
//Uri.encodeComponent('{"appId": 5,"platform": 3,"version": "1.46.2","abtest": ""}');
|
// 请求时会自动encodeComponent
|
||||||
|
|
||||||
static const urlPattern =
|
static const urlPattern =
|
||||||
r'https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]';
|
r'https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]';
|
||||||
|
|||||||
@@ -619,7 +619,7 @@ class Api {
|
|||||||
|
|
||||||
/// 申请二维码(TV端)
|
/// 申请二维码(TV端)
|
||||||
static const getTVCode =
|
static const getTVCode =
|
||||||
'https://passport.bilibili.com/x/passport-tv-login/qrcode/auth_code';
|
'${HttpString.passBaseUrl}/x/passport-tv-login/qrcode/auth_code';
|
||||||
|
|
||||||
///扫码登录(TV端)
|
///扫码登录(TV端)
|
||||||
static const qrcodePoll =
|
static const qrcodePoll =
|
||||||
@@ -662,7 +662,7 @@ class Api {
|
|||||||
static const getUnreadDynamic = '/x/web-interface/dynamic/entrance';
|
static const getUnreadDynamic = '/x/web-interface/dynamic/entrance';
|
||||||
|
|
||||||
/// 用户动态主页
|
/// 用户动态主页
|
||||||
static const dynamicSpmPrefix = 'https://space.bilibili.com/1/dynamic';
|
static const dynamicSpmPrefix = '${HttpString.spaceBaseUrl}/1/dynamic';
|
||||||
|
|
||||||
/// 激活buvid3
|
/// 激活buvid3
|
||||||
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
|
static const activateBuvidApi = '/x/internal/gaia-gateway/ExClimbWuzhi';
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import 'dart:developer';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:math' show Random;
|
import 'dart:math' show Random;
|
||||||
import 'package:PiliPlus/build_config.dart';
|
import 'package:PiliPlus/build_config.dart';
|
||||||
|
import 'package:archive/archive.dart';
|
||||||
|
import 'package:brotli/brotli.dart';
|
||||||
import 'package:cookie_jar/cookie_jar.dart';
|
import 'package:cookie_jar/cookie_jar.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:dio/io.dart';
|
import 'package:dio/io.dart';
|
||||||
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
||||||
|
import 'package:dio_http2_adapter/dio_http2_adapter.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:PiliPlus/utils/id_utils.dart';
|
import 'package:PiliPlus/utils/id_utils.dart';
|
||||||
import '../utils/storage.dart';
|
import '../utils/storage.dart';
|
||||||
@@ -18,6 +21,9 @@ import 'interceptor.dart';
|
|||||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart' as web;
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
|
static const gzipDecoder = GZipDecoder();
|
||||||
|
static const brotilDecoder = BrotliDecoder();
|
||||||
|
|
||||||
static final Request _instance = Request._internal();
|
static final Request _instance = Request._internal();
|
||||||
static late CookieManager cookieManager;
|
static late CookieManager cookieManager;
|
||||||
static late final Dio dio;
|
static late final Dio dio;
|
||||||
@@ -52,18 +58,18 @@ class Request {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
final userInfo = GStorage.userInfo.get('userInfoCache');
|
final userInfo = GStorage.userInfo.get('userInfoCache');
|
||||||
if (userInfo != null && userInfo.mid != null) {
|
if (userInfo?.mid != null) {
|
||||||
final List<Cookie> cookie2 = await cookieManager.cookieJar
|
final List<Cookie> tUrlCookies = await cookieManager.cookieJar
|
||||||
.loadForRequest(Uri.parse(HttpString.tUrl));
|
.loadForRequest(Uri.parse(HttpString.tUrl));
|
||||||
if (cookie2.isEmpty) {
|
if (tUrlCookies.isEmpty) {
|
||||||
try {
|
try {
|
||||||
await Request().get(HttpString.tUrl);
|
await dio.head(HttpString.tUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log("setCookie, ${e.toString()}");
|
log("setCookie, ${e.toString()}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setOptionsHeaders(userInfo);
|
||||||
}
|
}
|
||||||
setOptionsHeaders(userInfo, userInfo != null && userInfo.mid != null);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await buvidActivate();
|
await buvidActivate();
|
||||||
@@ -81,24 +87,16 @@ class Request {
|
|||||||
static Future<String> getCsrf() async {
|
static Future<String> getCsrf() async {
|
||||||
List<Cookie> cookies = await cookieManager.cookieJar
|
List<Cookie> cookies = await cookieManager.cookieJar
|
||||||
.loadForRequest(Uri.parse(HttpString.apiBaseUrl));
|
.loadForRequest(Uri.parse(HttpString.apiBaseUrl));
|
||||||
String token = '';
|
return cookies
|
||||||
if (cookies.where((e) => e.name == 'bili_jct').isNotEmpty) {
|
.firstWhere((e) => e.name == 'bili_jct', orElse: () => Cookie('', ''))
|
||||||
token = cookies.firstWhere((e) => e.name == 'bili_jct').value;
|
.value;
|
||||||
}
|
|
||||||
return token;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static setOptionsHeaders(userInfo, bool status) {
|
static setOptionsHeaders(userInfo) {
|
||||||
if (status) {
|
|
||||||
dio.options.headers['x-bili-mid'] = userInfo.mid.toString();
|
dio.options.headers['x-bili-mid'] = userInfo.mid.toString();
|
||||||
dio.options.headers['x-bili-aurora-eid'] =
|
dio.options.headers['x-bili-aurora-eid'] =
|
||||||
IdUtils.genAuroraEid(userInfo.mid);
|
IdUtils.genAuroraEid(userInfo.mid);
|
||||||
}
|
}
|
||||||
dio.options.headers['env'] = 'prod';
|
|
||||||
dio.options.headers['app-key'] = 'android64';
|
|
||||||
dio.options.headers['x-bili-aurora-zone'] = 'sh001';
|
|
||||||
dio.options.headers['referer'] = 'https://www.bilibili.com/';
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future buvidActivate() async {
|
static Future buvidActivate() async {
|
||||||
var html = await Request().get(Api.dynamicSpmPrefix);
|
var html = await Request().get(Api.dynamicSpmPrefix);
|
||||||
@@ -121,7 +119,7 @@ class Request {
|
|||||||
|
|
||||||
await Request().post(Api.activateBuvidApi,
|
await Request().post(Api.activateBuvidApi,
|
||||||
data: {'payload': jsonData},
|
data: {'payload': jsonData},
|
||||||
options: Options(contentType: 'application/json'));
|
options: Options(contentType: Headers.jsonContentType));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -137,8 +135,17 @@ class Request {
|
|||||||
//响应流上前后两次接受到数据的间隔,单位为毫秒。
|
//响应流上前后两次接受到数据的间隔,单位为毫秒。
|
||||||
receiveTimeout: const Duration(milliseconds: 12000),
|
receiveTimeout: const Duration(milliseconds: 12000),
|
||||||
//Http请求头.
|
//Http请求头.
|
||||||
headers: {},
|
headers: {
|
||||||
);
|
'connection': 'keep-alive',
|
||||||
|
'accept-encoding': 'br,gzip',
|
||||||
|
'user-agent': 'Dart/3.6 (dart:io)', // Http2Adapter不会自动添加标头
|
||||||
|
'referer': HttpString.baseUrl,
|
||||||
|
'env': 'prod',
|
||||||
|
'app-key': 'android64',
|
||||||
|
'x-bili-aurora-zone': 'sh001',
|
||||||
|
},
|
||||||
|
responseDecoder: responseDecoder, // Http2Adapter没有自动解压
|
||||||
|
persistentConnection: true);
|
||||||
|
|
||||||
enableSystemProxy = GStorage.setting
|
enableSystemProxy = GStorage.setting
|
||||||
.get(SettingBoxKey.enableSystemProxy, defaultValue: false) as bool;
|
.get(SettingBoxKey.enableSystemProxy, defaultValue: false) as bool;
|
||||||
@@ -147,33 +154,36 @@ class Request {
|
|||||||
systemProxyPort =
|
systemProxyPort =
|
||||||
GStorage.setting.get(SettingBoxKey.systemProxyPort, defaultValue: '');
|
GStorage.setting.get(SettingBoxKey.systemProxyPort, defaultValue: '');
|
||||||
|
|
||||||
dio = Dio(options);
|
final http11Adapter = IOHttpClientAdapter(createHttpClient: () {
|
||||||
|
final client = HttpClient()
|
||||||
/// fix 第三方登录 302重定向 跟iOS代理问题冲突
|
..idleTimeout = const Duration(seconds: 30)
|
||||||
// ..httpClientAdapter = Http2Adapter(
|
..autoUncompress = false; // Http2Adapter没有自动解压, 统一行为
|
||||||
// ConnectionManager(
|
// 设置代理
|
||||||
// idleTimeout: const Duration(milliseconds: 10000),
|
|
||||||
// onClientCreate: (context, ClientSetting config) =>
|
|
||||||
// config.onBadCertificate = (_) => true,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
|
|
||||||
/// 设置代理
|
|
||||||
if (enableSystemProxy) {
|
if (enableSystemProxy) {
|
||||||
dio.httpClientAdapter = IOHttpClientAdapter(
|
client.findProxy = (_) => 'PROXY $systemProxyHost:$systemProxyPort';
|
||||||
createHttpClient: () {
|
|
||||||
final HttpClient client = HttpClient();
|
|
||||||
// Config the client.
|
|
||||||
client.findProxy = (Uri uri) {
|
|
||||||
// return 'PROXY host:port';
|
|
||||||
return 'PROXY $systemProxyHost:$systemProxyPort';
|
|
||||||
};
|
|
||||||
client.badCertificateCallback =
|
client.badCertificateCallback =
|
||||||
(X509Certificate cert, String host, int port) => true;
|
(X509Certificate cert, String host, int port) => true;
|
||||||
return client;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
return client;
|
||||||
|
});
|
||||||
|
|
||||||
|
dio = Dio(options)
|
||||||
|
..httpClientAdapter =
|
||||||
|
GStorage.setting.get(SettingBoxKey.enableHttp2, defaultValue: false)
|
||||||
|
? Http2Adapter(
|
||||||
|
ConnectionManager(
|
||||||
|
idleTimeout: const Duration(seconds: 30),
|
||||||
|
onClientCreate: (_, ClientSetting config) {
|
||||||
|
config.onBadCertificate = (_) => true;
|
||||||
|
if (enableSystemProxy) {
|
||||||
|
config.proxy = Uri(
|
||||||
|
scheme: 'http',
|
||||||
|
host: systemProxyHost,
|
||||||
|
port: int.parse(systemProxyPort));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
fallbackAdapter: http11Adapter)
|
||||||
|
: http11Adapter;
|
||||||
|
|
||||||
// 日志拦截器 输出请求、响应内容
|
// 日志拦截器 输出请求、响应内容
|
||||||
if (BuildConfig.isDebug) {
|
if (BuildConfig.isDebug) {
|
||||||
@@ -186,8 +196,7 @@ class Request {
|
|||||||
|
|
||||||
dio.transformer = BackgroundTransformer();
|
dio.transformer = BackgroundTransformer();
|
||||||
dio.options.validateStatus = (int? status) {
|
dio.options.validateStatus = (int? status) {
|
||||||
return status! >= 200 && status < 300 ||
|
return status! >= 200 && status < 300;
|
||||||
HttpString.validateStatusCodes.contains(status);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,19 +294,24 @@ class Request {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String headerUa({type = 'mob'}) {
|
static String headerUa({type = 'mob'}) {
|
||||||
String headerUa = '';
|
return type == 'mob'
|
||||||
if (type == 'mob') {
|
? Platform.isIOS
|
||||||
if (Platform.isIOS) {
|
? 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1'
|
||||||
headerUa =
|
: 'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36'
|
||||||
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1';
|
: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15';
|
||||||
} else {
|
|
||||||
headerUa =
|
|
||||||
'Mozilla/5.0 (Linux; Android 10; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Mobile Safari/537.36';
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
headerUa =
|
static String responseDecoder(List<int> responseBytes, RequestOptions options,
|
||||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15';
|
ResponseBody responseBody) {
|
||||||
|
switch (responseBody.headers['content-encoding']?.firstOrNull) {
|
||||||
|
case 'gzip':
|
||||||
|
return utf8.decode(gzipDecoder.decodeBytes(responseBytes),
|
||||||
|
allowMalformed: true);
|
||||||
|
case 'br':
|
||||||
|
return utf8.decode(brotilDecoder.convert(responseBytes),
|
||||||
|
allowMalformed: true);
|
||||||
|
default:
|
||||||
|
return utf8.decode(responseBytes, allowMalformed: true);
|
||||||
}
|
}
|
||||||
return headerUa;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class ApiInterceptor extends Interceptor {
|
|||||||
options.headers.remove('x-bili-mid');
|
options.headers.remove('x-bili-mid');
|
||||||
options.headers.remove('x-bili-aurora-eid');
|
options.headers.remove('x-bili-aurora-eid');
|
||||||
options.headers.remove('x-bili-aurora-zone');
|
options.headers.remove('x-bili-aurora-zone');
|
||||||
options.headers['cookie'] = '';
|
options.headers.remove('cookie');
|
||||||
options.queryParameters.remove('access_key');
|
options.queryParameters.remove('access_key');
|
||||||
options.queryParameters.remove('csrf');
|
options.queryParameters.remove('csrf');
|
||||||
options.queryParameters.remove('csrf_token');
|
options.queryParameters.remove('csrf_token');
|
||||||
@@ -45,7 +45,7 @@ class ApiInterceptor extends Interceptor {
|
|||||||
|
|
||||||
// app端不需要cookie
|
// app端不需要cookie
|
||||||
if (options.uri.host == 'app.bilibili.com') {
|
if (options.uri.host == 'app.bilibili.com') {
|
||||||
options.headers['cookie'] = '';
|
options.headers.remove('cookie');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.extra['clearCookie'] == true) {
|
if (options.extra['clearCookie'] == true) {
|
||||||
@@ -139,5 +139,5 @@ class ApiInterceptor extends Interceptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension _ConnectivityResultExt on ConnectivityResult {
|
extension _ConnectivityResultExt on ConnectivityResult {
|
||||||
String get title => ['蓝牙', 'Wi-Fi', '局域', '流量', '无', '代理', '其他'][index];
|
String get title => const ['蓝牙', 'Wi-Fi', '局域', '流量', '无', '代理', '其他'][index];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ class VideoHttp {
|
|||||||
Api.recommendListApp,
|
Api.recommendListApp,
|
||||||
queryParameters: data,
|
queryParameters: data,
|
||||||
options: Options(headers: {
|
options: Options(headers: {
|
||||||
'Host': 'app.bilibili.com',
|
|
||||||
'buvid': LoginHttp.buvid,
|
'buvid': LoginHttp.buvid,
|
||||||
'fp_local':
|
'fp_local':
|
||||||
'1111111111111111111111111111111111111111111111111111111111111111',
|
'1111111111111111111111111111111111111111111111111111111111111111',
|
||||||
|
|||||||
@@ -54,9 +54,7 @@ void main() async {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (BuildConfig.isDebug || GStorage.badCertificateCallback) {
|
|
||||||
HttpOverrides.global = _CustomHttpOverrides();
|
HttpOverrides.global = _CustomHttpOverrides();
|
||||||
}
|
|
||||||
await setupServiceLocator();
|
await setupServiceLocator();
|
||||||
Request();
|
Request();
|
||||||
await Request.setCookie();
|
await Request.setCookie();
|
||||||
@@ -294,10 +292,18 @@ class MyApp extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CustomHttpOverrides extends HttpOverrides {
|
class _CustomHttpOverrides extends HttpOverrides {
|
||||||
|
static final badCertificateCallback =
|
||||||
|
BuildConfig.isDebug || GStorage.badCertificateCallback;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
HttpClient createHttpClient(SecurityContext? context) {
|
HttpClient createHttpClient(SecurityContext? context) {
|
||||||
return super.createHttpClient(context)
|
final client = super.createHttpClient(context)
|
||||||
..badCertificateCallback =
|
..maxConnectionsPerHost = 32
|
||||||
|
..idleTimeout = const Duration(seconds: 30);
|
||||||
|
if (badCertificateCallback) {
|
||||||
|
client.badCertificateCallback =
|
||||||
(X509Certificate cert, String host, int port) => true;
|
(X509Certificate cert, String host, int port) => true;
|
||||||
}
|
}
|
||||||
|
return client;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2181,6 +2181,14 @@ List<SettingsModel> get extraSettings => [
|
|||||||
setKey: SettingBoxKey.defaultShowComment,
|
setKey: SettingBoxKey.defaultShowComment,
|
||||||
defaultVal: false,
|
defaultVal: false,
|
||||||
),
|
),
|
||||||
|
SettingsModel(
|
||||||
|
settingsType: SettingsType.sw1tch,
|
||||||
|
title: '启用HTTP/2',
|
||||||
|
subtitle: '测试中',
|
||||||
|
leading: Icon(Icons.swap_horizontal_circle_outlined),
|
||||||
|
setKey: SettingBoxKey.enableHttp2,
|
||||||
|
defaultVal: false,
|
||||||
|
),
|
||||||
SettingsModel(
|
SettingsModel(
|
||||||
settingsType: SettingsType.normal,
|
settingsType: SettingsType.normal,
|
||||||
title: '评论展示',
|
title: '评论展示',
|
||||||
|
|||||||
@@ -644,6 +644,7 @@ class SettingBoxKey {
|
|||||||
expandDynLivePanel = 'expandDynLivePanel',
|
expandDynLivePanel = 'expandDynLivePanel',
|
||||||
springDescription = 'springDescription',
|
springDescription = 'springDescription',
|
||||||
collapsibleVideoPage = 'collapsibleVideoPage',
|
collapsibleVideoPage = 'collapsibleVideoPage',
|
||||||
|
enableHttp2 = 'enableHttp2',
|
||||||
|
|
||||||
// Sponsor Block
|
// Sponsor Block
|
||||||
enableSponsorBlock = 'enableSponsorBlock',
|
enableSponsorBlock = 'enableSponsorBlock',
|
||||||
|
|||||||
Reference in New Issue
Block a user