diff --git a/app/src/main/java/io/legado/app/App.kt b/app/src/main/java/io/legado/app/App.kt index 6345cf1b1..b5edcd40f 100644 --- a/app/src/main/java/io/legado/app/App.kt +++ b/app/src/main/java/io/legado/app/App.kt @@ -15,7 +15,7 @@ import io.legado.app.help.ActivityHelp import io.legado.app.help.AppConfig import io.legado.app.help.CrashHandler import io.legado.app.help.ThemeConfig.applyDayNight -import io.legado.app.help.http.HttpHelper +import io.legado.app.help.http.okHttpClient import io.legado.app.utils.LanguageUtils import io.legado.app.utils.defaultSharedPreferences import rxhttp.wrapper.param.RxHttp @@ -26,7 +26,7 @@ class App : MultiDexApplication() { super.onCreate() CrashHandler(this) LanguageUtils.setConfiguration(this) - RxHttp.init(HttpHelper.client, BuildConfig.DEBUG) + RxHttp.init(okHttpClient, BuildConfig.DEBUG) RxHttp.setOnParamAssembly { it.addHeader(AppConst.UA_NAME, AppConfig.userAgent) } diff --git a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt index a6331d8a6..99037a3cd 100644 --- a/app/src/main/java/io/legado/app/help/http/HttpHelper.kt +++ b/app/src/main/java/io/legado/app/help/http/HttpHelper.kt @@ -1,102 +1,12 @@ package io.legado.app.help.http import kotlinx.coroutines.suspendCancellableCoroutine -import okhttp3.ConnectionSpec -import okhttp3.Credentials -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import java.net.InetSocketAddress -import java.net.Proxy -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.TimeUnit import kotlin.coroutines.resume @Suppress("unused") object HttpHelper { - private val proxyClientCache: ConcurrentHashMap by lazy { - ConcurrentHashMap() - } - - val client: OkHttpClient by lazy { - - val specs = arrayListOf( - ConnectionSpec.MODERN_TLS, - ConnectionSpec.COMPATIBLE_TLS, - ConnectionSpec.CLEARTEXT - ) - - val builder = OkHttpClient.Builder() - .connectTimeout(15, TimeUnit.SECONDS) - .writeTimeout(15, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) - .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory, SSLHelper.unsafeTrustManager) - .retryOnConnectionFailure(true) - .hostnameVerifier(SSLHelper.unsafeHostnameVerifier) - .connectionSpecs(specs) - .followRedirects(true) - .followSslRedirects(true) - .addInterceptor(headerInterceptor()) - - builder.build() - } - - /** - * 缓存代理okHttp - */ - fun getProxyClient(proxy: String? = null): OkHttpClient { - if (proxy.isNullOrBlank()) { - return client - } - proxyClientCache[proxy]?.let { - return it - } - val r = Regex("(http|socks4|socks5)://(.*):(\\d{2,5})(@.*@.*)?") - val ms = r.findAll(proxy) - val group = ms.first() - var username = "" //代理服务器验证用户名 - var password = "" //代理服务器验证密码 - val type = if (group.groupValues[1] == "http") "http" else "socks" - val host = group.groupValues[2] - val port = group.groupValues[3].toInt() - if (group.groupValues[4] != "") { - username = group.groupValues[4].split("@")[1] - password = group.groupValues[4].split("@")[2] - } - if (type != "direct" && host != "") { - val builder = client.newBuilder() - if (type == "http") { - builder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port))) - } else { - builder.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port))) - } - if (username != "" && password != "") { - builder.proxyAuthenticator { _, response -> //设置代理服务器账号密码 - val credential: String = Credentials.basic(username, password) - response.request.newBuilder() - .header("Proxy-Authorization", credential) - .build() - } - } - val proxyClient = builder.build() - proxyClientCache[proxy] = proxyClient - return proxyClient - } - return client - } - - private fun headerInterceptor(): Interceptor { - return Interceptor { chain -> - val request = chain.request() - .newBuilder() - .addHeader("Keep-Alive", "300") - .addHeader("Connection", "Keep-Alive") - .addHeader("Cache-Control", "no-cache") - .build() - chain.proceed(request) - } - } - + suspend fun ajax(params: AjaxWebView.AjaxParams): StrResponse = suspendCancellableCoroutine { block -> val webView = AjaxWebView() diff --git a/app/src/main/java/io/legado/app/help/http/OkHttpExtensions.kt b/app/src/main/java/io/legado/app/help/http/OkHttpExtensions.kt deleted file mode 100644 index d32d9f3d4..000000000 --- a/app/src/main/java/io/legado/app/help/http/OkHttpExtensions.kt +++ /dev/null @@ -1,49 +0,0 @@ -package io.legado.app.help.http - -import io.legado.app.utils.EncodingDetect -import io.legado.app.utils.UTF8BOMFighter -import kotlinx.coroutines.suspendCancellableCoroutine -import okhttp3.Call -import okhttp3.Callback -import okhttp3.Response -import okhttp3.ResponseBody -import java.io.IOException -import java.nio.charset.Charset -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException - -suspend fun Call.await(): Response = suspendCancellableCoroutine { block -> - - block.invokeOnCancellation { - cancel() - } - - enqueue(object : Callback { - override fun onFailure(call: Call, e: IOException) { - block.resumeWithException(e) - } - - override fun onResponse(call: Call, response: Response) { - block.resume(response) - } - }) - -} - -fun ResponseBody.text(encode: String? = null): String { - val responseBytes = UTF8BOMFighter.removeUTF8BOM(bytes()) - var charsetName: String? = encode - - charsetName?.let { - return String(responseBytes, Charset.forName(charsetName)) - } - - //根据http头判断 - contentType()?.charset()?.let { - return String(responseBytes, it) - } - - //根据内容判断 - charsetName = EncodingDetect.getHtmlEncode(responseBytes) - return String(responseBytes, Charset.forName(charsetName)) -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt b/app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt new file mode 100644 index 000000000..a97e784c8 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt @@ -0,0 +1,131 @@ +package io.legado.app.help.http + +import io.legado.app.utils.EncodingDetect +import io.legado.app.utils.UTF8BOMFighter +import kotlinx.coroutines.suspendCancellableCoroutine +import okhttp3.* +import java.io.IOException +import java.net.InetSocketAddress +import java.net.Proxy +import java.nio.charset.Charset +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.TimeUnit +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException + +val okHttpClient: OkHttpClient by lazy { + + val specs = arrayListOf( + ConnectionSpec.MODERN_TLS, + ConnectionSpec.COMPATIBLE_TLS, + ConnectionSpec.CLEARTEXT + ) + + val builder = OkHttpClient.Builder() + .connectTimeout(15, TimeUnit.SECONDS) + .writeTimeout(15, TimeUnit.SECONDS) + .readTimeout(15, TimeUnit.SECONDS) + .sslSocketFactory(SSLHelper.unsafeSSLSocketFactory, SSLHelper.unsafeTrustManager) + .retryOnConnectionFailure(true) + .hostnameVerifier(SSLHelper.unsafeHostnameVerifier) + .connectionSpecs(specs) + .followRedirects(true) + .followSslRedirects(true) + .addInterceptor(Interceptor { chain -> + val request = chain.request() + .newBuilder() + .addHeader("Keep-Alive", "300") + .addHeader("Connection", "Keep-Alive") + .addHeader("Cache-Control", "no-cache") + .build() + chain.proceed(request) + }) + + builder.build() +} + +object OkHttpHelper { + private val proxyClientCache: ConcurrentHashMap by lazy { + ConcurrentHashMap() + } + + /** + * 缓存代理okHttp + */ + fun getProxyClient(proxy: String? = null): OkHttpClient { + if (proxy.isNullOrBlank()) { + return okHttpClient + } + proxyClientCache[proxy]?.let { + return it + } + val r = Regex("(http|socks4|socks5)://(.*):(\\d{2,5})(@.*@.*)?") + val ms = r.findAll(proxy) + val group = ms.first() + var username = "" //代理服务器验证用户名 + var password = "" //代理服务器验证密码 + val type = if (group.groupValues[1] == "http") "http" else "socks" + val host = group.groupValues[2] + val port = group.groupValues[3].toInt() + if (group.groupValues[4] != "") { + username = group.groupValues[4].split("@")[1] + password = group.groupValues[4].split("@")[2] + } + if (type != "direct" && host != "") { + val builder = okHttpClient.newBuilder() + if (type == "http") { + builder.proxy(Proxy(Proxy.Type.HTTP, InetSocketAddress(host, port))) + } else { + builder.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress(host, port))) + } + if (username != "" && password != "") { + builder.proxyAuthenticator { _, response -> //设置代理服务器账号密码 + val credential: String = Credentials.basic(username, password) + response.request.newBuilder() + .header("Proxy-Authorization", credential) + .build() + } + } + val proxyClient = builder.build() + proxyClientCache[proxy] = proxyClient + return proxyClient + } + return okHttpClient + } +} + +suspend fun Call.await(): Response = suspendCancellableCoroutine { block -> + + block.invokeOnCancellation { + cancel() + } + + enqueue(object : Callback { + override fun onFailure(call: Call, e: IOException) { + block.resumeWithException(e) + } + + override fun onResponse(call: Call, response: Response) { + block.resume(response) + } + }) + +} + +fun ResponseBody.text(encode: String? = null): String { + val responseBytes = UTF8BOMFighter.removeUTF8BOM(bytes()) + var charsetName: String? = encode + + charsetName?.let { + return String(responseBytes, Charset.forName(charsetName)) + } + + //根据http头判断 + contentType()?.charset()?.let { + return String(responseBytes, it) + } + + //根据内容判断 + charsetName = EncodingDetect.getHtmlEncode(responseBytes) + return String(responseBytes, Charset.forName(charsetName)) +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt index 51c8e93ae..612781028 100644 --- a/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt +++ b/app/src/main/java/io/legado/app/lib/webdav/WebDav.kt @@ -1,7 +1,7 @@ package io.legado.app.lib.webdav -import io.legado.app.help.http.HttpHelper import io.legado.app.help.http.await +import io.legado.app.help.http.okHttpClient import okhttp3.* import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.asRequestBody @@ -113,7 +113,7 @@ class WebDav(urlStr: String) { request.header("Authorization", Credentials.basic(it.user, it.pass)) } request.header("Depth", if (depth < 0) "infinity" else depth.toString()) - return HttpHelper.client.newCall(request.build()).await() + return okHttpClient.newCall(request.build()).await() } return null } @@ -227,7 +227,7 @@ class WebDav(urlStr: String) { HttpAuth.auth?.let { requestBuilder.header("Authorization", Credentials.basic(it.user, it.pass)) } - val response = HttpHelper.client.newCall(requestBuilder.build()).await() + val response = okHttpClient.newCall(requestBuilder.build()).await() return response.isSuccessful } @@ -239,7 +239,7 @@ class WebDav(urlStr: String) { val requestBuilder = Request.Builder() .url(url) .addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) - return HttpHelper.client.newCall(request = requestBuilder.build()).await() + return okHttpClient.newCall(request = requestBuilder.build()).await() .body?.byteStream() } return null diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt index 318c1dcd3..0dc588990 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt @@ -312,14 +312,14 @@ class AnalyzeUrl( if (fieldMap.isNotEmpty() || body.isNullOrBlank()) { RxHttp.postForm(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAllEncoded(fieldMap) .addAllHeader(headerMap) .toStrResponse().await() } else { RxHttp.postJson(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAll(body) .addAllHeader(headerMap) .toStrResponse().await() @@ -327,7 +327,7 @@ class AnalyzeUrl( } else -> RxHttp.get(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAllEncoded(fieldMap) .addAllHeader(headerMap) .toStrResponse().await() @@ -341,14 +341,14 @@ class AnalyzeUrl( if (fieldMap.isNotEmpty() || body.isNullOrBlank()) { RxHttp.postForm(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAllEncoded(fieldMap) .addAllHeader(headerMap) .toByteArray().await() } else { RxHttp.postJson(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAll(body) .addAllHeader(headerMap) .toByteArray().await() @@ -356,7 +356,7 @@ class AnalyzeUrl( } else -> RxHttp.get(url) .setAssemblyEnabled(false) - .setOkClient(HttpHelper.getProxyClient(proxy)) + .setOkClient(OkHttpHelper.getProxyClient(proxy)) .addAllEncoded(fieldMap) .addAllHeader(headerMap) .toByteArray().await()