mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-05-21 18:03:04 +00:00
Update m_client.dart
- getCookiesPref() and deleteAllCookies(): Avoid repeated parsing of `Uri.parse(url).host` by creating a variable. - httpClient(): cache RhttpCompatibleClients and add default IOClient fallback. - shouldAttemptRetryOnResponse(): Added a delay to avoid busy looping.
This commit is contained in:
parent
4f1e2cb492
commit
ca4cee5751
1 changed files with 53 additions and 59 deletions
|
|
@ -15,6 +15,8 @@ import 'package:mangayomi/services/http/rhttp/rhttp.dart' as rhttp;
|
||||||
|
|
||||||
class MClient {
|
class MClient {
|
||||||
MClient();
|
MClient();
|
||||||
|
static final defaultClient = IOClient(HttpClient());
|
||||||
|
static final Map<rhttp.ClientSettings, Client> rhttpPool = {};
|
||||||
static Client httpClient({
|
static Client httpClient({
|
||||||
Map<String, dynamic>? reqcopyWith,
|
Map<String, dynamic>? reqcopyWith,
|
||||||
rhttp.ClientSettings? settings,
|
rhttp.ClientSettings? settings,
|
||||||
|
|
@ -41,10 +43,12 @@ class MClient {
|
||||||
verifyCertificates: reqcopyWith?["verifyCertificates"] ?? false,
|
verifyCertificates: reqcopyWith?["verifyCertificates"] ?? false,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return rhttp.RhttpCompatibleClient.createSync(settings: settings);
|
return rhttpPool.putIfAbsent(settings, () {
|
||||||
|
return rhttp.RhttpCompatibleClient.createSync(settings: settings);
|
||||||
|
});
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
return IOClient(HttpClient());
|
return defaultClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
static InterceptedClient init({
|
static InterceptedClient init({
|
||||||
|
|
@ -66,12 +70,11 @@ class MClient {
|
||||||
static Map<String, String> getCookiesPref(String url) {
|
static Map<String, String> getCookiesPref(String url) {
|
||||||
final cookiesList = isar.settings.getSync(227)!.cookiesList ?? [];
|
final cookiesList = isar.settings.getSync(227)!.cookiesList ?? [];
|
||||||
if (cookiesList.isEmpty) return {};
|
if (cookiesList.isEmpty) return {};
|
||||||
|
final host = Uri.parse(url).host;
|
||||||
final cookies =
|
final cookies =
|
||||||
cookiesList
|
cookiesList
|
||||||
.firstWhere(
|
.firstWhere(
|
||||||
(element) =>
|
(element) => element.host == host || host.contains(element.host!),
|
||||||
element.host == Uri.parse(url).host ||
|
|
||||||
Uri.parse(url).host.contains(element.host!),
|
|
||||||
orElse: () => MCookie(cookie: ""),
|
orElse: () => MCookie(cookie: ""),
|
||||||
)
|
)
|
||||||
.cookie!;
|
.cookie!;
|
||||||
|
|
@ -93,56 +96,51 @@ class MClient {
|
||||||
.split(RegExp('(?<=)(,)(?=[^;]+?=)'))
|
.split(RegExp('(?<=)(,)(?=[^;]+?=)'))
|
||||||
.where((cookie) => cookie.isNotEmpty)
|
.where((cookie) => cookie.isNotEmpty)
|
||||||
.toList();
|
.toList();
|
||||||
} else {
|
} else if (!Platform.isLinux) {
|
||||||
if (!Platform.isLinux) {
|
cookies =
|
||||||
cookies =
|
(await flutter_inappwebview.CookieManager.instance(
|
||||||
(await flutter_inappwebview.CookieManager.instance(
|
webViewEnvironment: webViewEnvironment,
|
||||||
webViewEnvironment: webViewEnvironment,
|
).getCookies(
|
||||||
).getCookies(
|
url: flutter_inappwebview.WebUri(url),
|
||||||
url: flutter_inappwebview.WebUri(url),
|
webViewController: webViewController,
|
||||||
webViewController: webViewController,
|
)).map((e) => "${e.name}=${e.value}").toList();
|
||||||
)).map((e) => "${e.name}=${e.value}").toList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (cookies.isNotEmpty) {
|
if (cookies.isNotEmpty) {
|
||||||
final host = Uri.parse(url).host;
|
final host = Uri.parse(url).host;
|
||||||
final newCookie = cookies.join("; ");
|
final newCookie = cookies.join("; ");
|
||||||
final settings = isar.settings.getSync(227);
|
final settings = await isar.settings.get(227);
|
||||||
List<MCookie>? cookieList = [];
|
final existingCookies = settings!.cookiesList ?? [];
|
||||||
for (var cookie in settings!.cookiesList ?? []) {
|
final filteredCookies = removeCookiesForHost(existingCookies, host);
|
||||||
if (cookie.host != host || (!host.contains(cookie.host))) {
|
filteredCookies.add(
|
||||||
cookieList.add(cookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cookieList.add(
|
|
||||||
MCookie()
|
MCookie()
|
||||||
..host = host
|
..host = host
|
||||||
..cookie = newCookie,
|
..cookie = newCookie,
|
||||||
);
|
);
|
||||||
isar.writeTxnSync(
|
await isar.writeTxn(
|
||||||
() => isar.settings.putSync(settings..cookiesList = cookieList),
|
() => isar.settings.put(settings..cookiesList = filteredCookies),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (ua.isNotEmpty) {
|
if (ua.isNotEmpty) {
|
||||||
final settings = isar.settings.getSync(227);
|
final settings = await isar.settings.get(227);
|
||||||
isar.writeTxnSync(() => isar.settings.putSync(settings!..userAgent = ua));
|
await isar.writeTxn(() => isar.settings.put(settings!..userAgent = ua));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deleteAllCookies(String url) {
|
static List<MCookie> removeCookiesForHost(
|
||||||
final cookiesList = isar.settings.getSync(227)!.cookiesList ?? [];
|
List<MCookie> allCookies,
|
||||||
List<MCookie>? cookieList = [];
|
String host,
|
||||||
for (var cookie in cookiesList) {
|
) {
|
||||||
if (!(cookie.host == Uri.parse(url).host ||
|
return allCookies
|
||||||
Uri.parse(url).host.contains(cookie.host!))) {
|
.where((cookie) => cookie.host != host && !host.contains(cookie.host!))
|
||||||
cookieList.add(cookie);
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
isar.writeTxnSync(
|
static Future<void> deleteAllCookies(String url) async {
|
||||||
() => isar.settings.putSync(
|
final settings = await isar.settings.get(227);
|
||||||
isar.settings.getSync(227)!..cookiesList = cookieList,
|
final oldCookies = settings!.cookiesList ?? [];
|
||||||
),
|
final host = Uri.parse(url).host;
|
||||||
);
|
settings.cookiesList = removeCookiesForHost(oldCookies, host);
|
||||||
|
await isar.writeTxn(() => isar.settings.put(settings));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,7 +152,8 @@ class MCookieManager extends InterceptorContract {
|
||||||
Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
|
Future<BaseRequest> interceptRequest({required BaseRequest request}) async {
|
||||||
final cookie = MClient.getCookiesPref(request.url.toString());
|
final cookie = MClient.getCookiesPref(request.url.toString());
|
||||||
if (cookie.isNotEmpty) {
|
if (cookie.isNotEmpty) {
|
||||||
final userAgent = isar.settings.getSync(227)!.userAgent!;
|
final settings = await isar.settings.get(227);
|
||||||
|
final userAgent = settings!.userAgent!;
|
||||||
if (request.headers[HttpHeaders.cookieHeader] == null) {
|
if (request.headers[HttpHeaders.cookieHeader] == null) {
|
||||||
request.headers.addAll(cookie);
|
request.headers.addAll(cookie);
|
||||||
}
|
}
|
||||||
|
|
@ -211,12 +210,7 @@ class LoggerInterceptor extends InterceptorContract {
|
||||||
required BaseResponse response,
|
required BaseResponse response,
|
||||||
}) async {
|
}) async {
|
||||||
if (showCloudFlareError) {
|
if (showCloudFlareError) {
|
||||||
final cloudflare =
|
final cloudflare = isCloudflare(response);
|
||||||
[403, 503].contains(response.statusCode) &&
|
|
||||||
[
|
|
||||||
"cloudflare-nginx",
|
|
||||||
"cloudflare",
|
|
||||||
].contains(response.headers["server"]);
|
|
||||||
final content =
|
final content =
|
||||||
"----- Response -----\n${response.request?.method}: ${response.request?.url}, statusCode: ${response.statusCode} ${cloudflare ? "Failed to bypass Cloudflare" : ""}";
|
"----- Response -----\n${response.request?.method}: ${response.request?.url}, statusCode: ${response.statusCode} ${cloudflare ? "Failed to bypass Cloudflare" : ""}";
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
|
|
@ -238,6 +232,11 @@ class LoggerInterceptor extends InterceptorContract {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isCloudflare(BaseResponse response) {
|
||||||
|
return [403, 503].contains(response.statusCode) &&
|
||||||
|
["cloudflare-nginx", "cloudflare"].contains(response.headers["server"]);
|
||||||
|
}
|
||||||
|
|
||||||
class ResolveCloudFlareChallenge extends RetryPolicy {
|
class ResolveCloudFlareChallenge extends RetryPolicy {
|
||||||
bool showCloudFlareError;
|
bool showCloudFlareError;
|
||||||
ResolveCloudFlareChallenge(this.showCloudFlareError);
|
ResolveCloudFlareChallenge(this.showCloudFlareError);
|
||||||
|
|
@ -249,11 +248,8 @@ class ResolveCloudFlareChallenge extends RetryPolicy {
|
||||||
flutter_inappwebview.HeadlessInAppWebView? headlessWebView;
|
flutter_inappwebview.HeadlessInAppWebView? headlessWebView;
|
||||||
int time = 0;
|
int time = 0;
|
||||||
bool timeOut = false;
|
bool timeOut = false;
|
||||||
final cloudflare =
|
bool isCloudFlare = isCloudflare(response);
|
||||||
[403, 503].contains(response.statusCode) &&
|
if (isCloudFlare) {
|
||||||
["cloudflare-nginx", "cloudflare"].contains(response.headers["server"]);
|
|
||||||
if (cloudflare) {
|
|
||||||
bool isCloudFlare = true;
|
|
||||||
headlessWebView = flutter_inappwebview.HeadlessInAppWebView(
|
headlessWebView = flutter_inappwebview.HeadlessInAppWebView(
|
||||||
webViewEnvironment: webViewEnvironment,
|
webViewEnvironment: webViewEnvironment,
|
||||||
initialUrlRequest: flutter_inappwebview.URLRequest(
|
initialUrlRequest: flutter_inappwebview.URLRequest(
|
||||||
|
|
@ -270,10 +266,7 @@ class ResolveCloudFlareChallenge extends RetryPolicy {
|
||||||
}
|
}
|
||||||
|
|
||||||
await Future.doWhile(() async {
|
await Future.doWhile(() async {
|
||||||
if (timeOut == true) {
|
if (!timeOut && isCloudFlare) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (isCloudFlare) {
|
|
||||||
try {
|
try {
|
||||||
isCloudFlare = await controller.platform.evaluateJavascript(
|
isCloudFlare = await controller.platform.evaluateJavascript(
|
||||||
source:
|
source:
|
||||||
|
|
@ -282,9 +275,10 @@ class ResolveCloudFlareChallenge extends RetryPolicy {
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
isCloudFlare = false;
|
isCloudFlare = false;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
if (isCloudFlare) await Future.delayed(Duration(milliseconds: 300));
|
||||||
|
|
||||||
|
return isCloudFlare;
|
||||||
});
|
});
|
||||||
if (!timeOut) {
|
if (!timeOut) {
|
||||||
final ua =
|
final ua =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue