diff --git a/lib/services/http/m_client.dart b/lib/services/http/m_client.dart index e4e3c0e3..099b27d3 100644 --- a/lib/services/http/m_client.dart +++ b/lib/services/http/m_client.dart @@ -15,6 +15,8 @@ import 'package:mangayomi/services/http/rhttp/rhttp.dart' as rhttp; class MClient { MClient(); + static final defaultClient = IOClient(HttpClient()); + static final Map rhttpPool = {}; static Client httpClient({ Map? reqcopyWith, rhttp.ClientSettings? settings, @@ -41,10 +43,12 @@ class MClient { verifyCertificates: reqcopyWith?["verifyCertificates"] ?? false, ), ); - return rhttp.RhttpCompatibleClient.createSync(settings: settings); + return rhttpPool.putIfAbsent(settings, () { + return rhttp.RhttpCompatibleClient.createSync(settings: settings); + }); } catch (_) {} } - return IOClient(HttpClient()); + return defaultClient; } static InterceptedClient init({ @@ -66,12 +70,11 @@ class MClient { static Map getCookiesPref(String url) { final cookiesList = isar.settings.getSync(227)!.cookiesList ?? []; if (cookiesList.isEmpty) return {}; + final host = Uri.parse(url).host; final cookies = cookiesList .firstWhere( - (element) => - element.host == Uri.parse(url).host || - Uri.parse(url).host.contains(element.host!), + (element) => element.host == host || host.contains(element.host!), orElse: () => MCookie(cookie: ""), ) .cookie!; @@ -93,56 +96,51 @@ class MClient { .split(RegExp('(?<=)(,)(?=[^;]+?=)')) .where((cookie) => cookie.isNotEmpty) .toList(); - } else { - if (!Platform.isLinux) { - cookies = - (await flutter_inappwebview.CookieManager.instance( - webViewEnvironment: webViewEnvironment, - ).getCookies( - url: flutter_inappwebview.WebUri(url), - webViewController: webViewController, - )).map((e) => "${e.name}=${e.value}").toList(); - } + } else if (!Platform.isLinux) { + cookies = + (await flutter_inappwebview.CookieManager.instance( + webViewEnvironment: webViewEnvironment, + ).getCookies( + url: flutter_inappwebview.WebUri(url), + webViewController: webViewController, + )).map((e) => "${e.name}=${e.value}").toList(); } if (cookies.isNotEmpty) { final host = Uri.parse(url).host; final newCookie = cookies.join("; "); - final settings = isar.settings.getSync(227); - List? cookieList = []; - for (var cookie in settings!.cookiesList ?? []) { - if (cookie.host != host || (!host.contains(cookie.host))) { - cookieList.add(cookie); - } - } - cookieList.add( + final settings = await isar.settings.get(227); + final existingCookies = settings!.cookiesList ?? []; + final filteredCookies = removeCookiesForHost(existingCookies, host); + filteredCookies.add( MCookie() ..host = host ..cookie = newCookie, ); - isar.writeTxnSync( - () => isar.settings.putSync(settings..cookiesList = cookieList), + await isar.writeTxn( + () => isar.settings.put(settings..cookiesList = filteredCookies), ); } if (ua.isNotEmpty) { - final settings = isar.settings.getSync(227); - isar.writeTxnSync(() => isar.settings.putSync(settings!..userAgent = ua)); + final settings = await isar.settings.get(227); + await isar.writeTxn(() => isar.settings.put(settings!..userAgent = ua)); } } - static void deleteAllCookies(String url) { - final cookiesList = isar.settings.getSync(227)!.cookiesList ?? []; - List? cookieList = []; - for (var cookie in cookiesList) { - if (!(cookie.host == Uri.parse(url).host || - Uri.parse(url).host.contains(cookie.host!))) { - cookieList.add(cookie); - } - } - isar.writeTxnSync( - () => isar.settings.putSync( - isar.settings.getSync(227)!..cookiesList = cookieList, - ), - ); + static List removeCookiesForHost( + List allCookies, + String host, + ) { + return allCookies + .where((cookie) => cookie.host != host && !host.contains(cookie.host!)) + .toList(); + } + + static Future deleteAllCookies(String url) async { + final settings = await isar.settings.get(227); + 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 interceptRequest({required BaseRequest request}) async { final cookie = MClient.getCookiesPref(request.url.toString()); 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) { request.headers.addAll(cookie); } @@ -211,12 +210,7 @@ class LoggerInterceptor extends InterceptorContract { required BaseResponse response, }) async { if (showCloudFlareError) { - final cloudflare = - [403, 503].contains(response.statusCode) && - [ - "cloudflare-nginx", - "cloudflare", - ].contains(response.headers["server"]); + final cloudflare = isCloudflare(response); final content = "----- Response -----\n${response.request?.method}: ${response.request?.url}, statusCode: ${response.statusCode} ${cloudflare ? "Failed to bypass Cloudflare" : ""}"; 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 { bool showCloudFlareError; ResolveCloudFlareChallenge(this.showCloudFlareError); @@ -249,11 +248,8 @@ class ResolveCloudFlareChallenge extends RetryPolicy { flutter_inappwebview.HeadlessInAppWebView? headlessWebView; int time = 0; bool timeOut = false; - final cloudflare = - [403, 503].contains(response.statusCode) && - ["cloudflare-nginx", "cloudflare"].contains(response.headers["server"]); - if (cloudflare) { - bool isCloudFlare = true; + bool isCloudFlare = isCloudflare(response); + if (isCloudFlare) { headlessWebView = flutter_inappwebview.HeadlessInAppWebView( webViewEnvironment: webViewEnvironment, initialUrlRequest: flutter_inappwebview.URLRequest( @@ -270,10 +266,7 @@ class ResolveCloudFlareChallenge extends RetryPolicy { } await Future.doWhile(() async { - if (timeOut == true) { - return false; - } - if (isCloudFlare) { + if (!timeOut && isCloudFlare) { try { isCloudFlare = await controller.platform.evaluateJavascript( source: @@ -282,9 +275,10 @@ class ResolveCloudFlareChallenge extends RetryPolicy { } catch (_) { isCloudFlare = false; } - return true; } - return false; + if (isCloudFlare) await Future.delayed(Duration(milliseconds: 300)); + + return isCloudFlare; }); if (!timeOut) { final ua =