From 6585a38925832c68c00589c97b10bce4064e0231 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Tue, 5 Dec 2023 20:58:28 -0500 Subject: [PATCH 1/2] Improve Http Client Configuration --- gradle/libs.versions.toml | 2 + .../kanade/tachiyomi/network/NetworkHelper.kt | 38 ++++++++++++++++--- .../UncaughtExceptionInterceptor.kt | 28 ++++++++++++++ .../suwayomi/tachidesk/manga/impl/Manga.kt | 5 ++- .../manga/impl/extension/Extension.kt | 8 ++-- 5 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5508a0416c..b6c660f372 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -42,6 +42,7 @@ kotlinlogging = "io.github.microutils:kotlin-logging:3.0.5" okhttp-core = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" } okhttp-dnsoverhttps = { module = "com.squareup.okhttp3:okhttp-dnsoverhttps", version.ref = "okhttp" } +okhttp-brotli = { module = "com.squareup.okhttp3:okhttp-brotli", version.ref = "okhttp" } okio = "com.squareup.okio:okio:3.3.0" # Javalin api @@ -195,6 +196,7 @@ okhttp = [ "okhttp-core", "okhttp-logging", "okhttp-dnsoverhttps", + "okhttp-brotli", ] javalin = [ "javalin-core", diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt index ff6e7d14be..bbd419fa51 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -16,10 +16,14 @@ package eu.kanade.tachiyomi.network // import uy.kohesive.injekt.injectLazy import android.content.Context import eu.kanade.tachiyomi.network.interceptor.CloudflareInterceptor +import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor import mu.KotlinLogging +import okhttp3.Cache import okhttp3.OkHttpClient +import okhttp3.brotli.BrotliInterceptor import okhttp3.logging.HttpLoggingInterceptor +import java.io.File import java.net.CookieHandler import java.net.CookieManager import java.net.CookiePolicy @@ -51,8 +55,17 @@ class NetworkHelper(context: Context) { .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .callTimeout(2, TimeUnit.MINUTES) + .cache( + Cache( + directory = File.createTempFile("tachidesk_network_cache", null), + maxSize = 5L * 1024 * 1024, // 5 MiB + ), + ) + .addInterceptor(BrotliInterceptor) + .addInterceptor(UncaughtExceptionInterceptor()) .addInterceptor(UserAgentInterceptor()) + //if (preferences.verboseLogging().get()) { val httpLoggingInterceptor = HttpLoggingInterceptor( object : HttpLoggingInterceptor.Logger { @@ -65,12 +78,27 @@ class NetworkHelper(context: Context) { ).apply { level = HttpLoggingInterceptor.Level.BASIC } - builder.addInterceptor(httpLoggingInterceptor) + builder.addNetworkInterceptor(httpLoggingInterceptor) + //} -// when (preferences.dohProvider()) { -// PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() -// PREF_DOH_GOOGLE -> builder.dohGoogle() -// } + // builder.addInterceptor( + // CloudflareInterceptor(context, cookieJar, ::defaultUserAgentProvider), + // ) + + // when (preferences.dohProvider().get()) { + // PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() + // PREF_DOH_GOOGLE -> builder.dohGoogle() + // PREF_DOH_ADGUARD -> builder.dohAdGuard() + // PREF_DOH_QUAD9 -> builder.dohQuad9() + // PREF_DOH_ALIDNS -> builder.dohAliDNS() + // PREF_DOH_DNSPOD -> builder.dohDNSPod() + // PREF_DOH_360 -> builder.doh360() + // PREF_DOH_QUAD101 -> builder.dohQuad101() + // PREF_DOH_MULLVAD -> builder.dohMullvad() + // PREF_DOH_CONTROLD -> builder.dohControlD() + // PREF_DOH_NJALLA -> builder.dohNajalla() + // PREF_DOH_SHECAN -> builder.dohShecan() + // } return builder } diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt new file mode 100644 index 0000000000..1de824381b --- /dev/null +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt @@ -0,0 +1,28 @@ +package eu.kanade.tachiyomi.network.interceptor + +import okhttp3.Interceptor +import okhttp3.Response +import java.io.IOException + +/** + * Catches any uncaught exceptions from later in the chain and rethrows as a non-fatal + * IOException to avoid catastrophic failure. + * + * This should be the first interceptor in the client. + * + * See https://square.github.io/okhttp/4.x/okhttp/okhttp3/-interceptor/ + */ +class UncaughtExceptionInterceptor : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + return try { + chain.proceed(chain.request()) + } catch (e: Exception) { + if (e is IOException) { + throw e + } else { + throw IOException(e) + } + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt index 977807bac5..d83f564962 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Manga.kt @@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.source.online.HttpSource import mu.KotlinLogging +import okhttp3.CacheControl import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.and @@ -280,7 +281,7 @@ object Manga { } source.client.newCall( - GET(thumbnailUrl, source.headers), + GET(thumbnailUrl, source.headers, cache = CacheControl.FORCE_NETWORK), ).await() } @@ -306,7 +307,7 @@ object Manga { mangaEntry[MangaTable.thumbnail_url] ?: throw NullPointerException("No thumbnail found") network.client.newCall( - GET(thumbnailUrl), + GET(thumbnailUrl, cache = CacheControl.FORCE_NETWORK), ).await() } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt index a06667815a..b6a005929f 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt @@ -14,6 +14,7 @@ import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceFactory import mu.KotlinLogging +import okhttp3.CacheControl import okhttp3.Request import okio.buffer import okio.sink @@ -272,8 +273,9 @@ object Extension { url: String, savePath: String, ) { - val request = Request.Builder().url(url).build() - val response = network.client.newCall(request).await() + val response = network.client.newCall( + GET(url, cache = CacheControl.FORCE_NETWORK) + ).await() val downloadedFile = File(savePath) downloadedFile.sink().buffer().use { sink -> @@ -350,7 +352,7 @@ object Extension { return getImageResponse(cacheSaveDir, apkName) { network.client.newCall( - GET(iconUrl), + GET(iconUrl, cache = CacheControl.FORCE_NETWORK), ).await() } } From 81031b862db9cae472ed09cbde3378bff779d2d6 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Tue, 5 Dec 2023 21:06:36 -0500 Subject: [PATCH 2/2] Lint --- .../kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt | 4 ++-- .../network/interceptor/UncaughtExceptionInterceptor.kt | 1 - .../suwayomi/tachidesk/manga/impl/extension/Extension.kt | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt index bbd419fa51..88a7187449 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -65,7 +65,7 @@ class NetworkHelper(context: Context) { .addInterceptor(UncaughtExceptionInterceptor()) .addInterceptor(UserAgentInterceptor()) - //if (preferences.verboseLogging().get()) { + // if (preferences.verboseLogging().get()) { val httpLoggingInterceptor = HttpLoggingInterceptor( object : HttpLoggingInterceptor.Logger { @@ -79,7 +79,7 @@ class NetworkHelper(context: Context) { level = HttpLoggingInterceptor.Level.BASIC } builder.addNetworkInterceptor(httpLoggingInterceptor) - //} + // } // builder.addInterceptor( // CloudflareInterceptor(context, cookieJar, ::defaultUserAgentProvider), diff --git a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt index 1de824381b..958dcd85d8 100644 --- a/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt +++ b/server/src/main/kotlin/eu/kanade/tachiyomi/network/interceptor/UncaughtExceptionInterceptor.kt @@ -13,7 +13,6 @@ import java.io.IOException * See https://square.github.io/okhttp/4.x/okhttp/okhttp3/-interceptor/ */ class UncaughtExceptionInterceptor : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { return try { chain.proceed(chain.request()) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt index b6a005929f..abc998025d 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/extension/Extension.kt @@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceFactory import mu.KotlinLogging import okhttp3.CacheControl -import okhttp3.Request import okio.buffer import okio.sink import okio.source @@ -273,9 +272,10 @@ object Extension { url: String, savePath: String, ) { - val response = network.client.newCall( - GET(url, cache = CacheControl.FORCE_NETWORK) - ).await() + val response = + network.client.newCall( + GET(url, cache = CacheControl.FORCE_NETWORK), + ).await() val downloadedFile = File(savePath) downloadedFile.sink().buffer().use { sink ->