pull/977/head
gedoor 4 years ago
parent da0d070bfe
commit d9bcb7506a
  1. 4
      app/src/main/java/io/legado/app/App.kt
  2. 90
      app/src/main/java/io/legado/app/help/http/HttpHelper.kt
  3. 49
      app/src/main/java/io/legado/app/help/http/OkHttpExtensions.kt
  4. 131
      app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt
  5. 8
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  6. 12
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@ -15,7 +15,7 @@ import io.legado.app.help.ActivityHelp
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CrashHandler import io.legado.app.help.CrashHandler
import io.legado.app.help.ThemeConfig.applyDayNight 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.LanguageUtils
import io.legado.app.utils.defaultSharedPreferences import io.legado.app.utils.defaultSharedPreferences
import rxhttp.wrapper.param.RxHttp import rxhttp.wrapper.param.RxHttp
@ -26,7 +26,7 @@ class App : MultiDexApplication() {
super.onCreate() super.onCreate()
CrashHandler(this) CrashHandler(this)
LanguageUtils.setConfiguration(this) LanguageUtils.setConfiguration(this)
RxHttp.init(HttpHelper.client, BuildConfig.DEBUG) RxHttp.init(okHttpClient, BuildConfig.DEBUG)
RxHttp.setOnParamAssembly { RxHttp.setOnParamAssembly {
it.addHeader(AppConst.UA_NAME, AppConfig.userAgent) it.addHeader(AppConst.UA_NAME, AppConfig.userAgent)
} }

@ -1,101 +1,11 @@
package io.legado.app.help.http package io.legado.app.help.http
import kotlinx.coroutines.suspendCancellableCoroutine 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 import kotlin.coroutines.resume
@Suppress("unused") @Suppress("unused")
object HttpHelper { object HttpHelper {
private val proxyClientCache: ConcurrentHashMap<String, OkHttpClient> 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 = suspend fun ajax(params: AjaxWebView.AjaxParams): StrResponse =
suspendCancellableCoroutine { block -> suspendCancellableCoroutine { block ->

@ -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))
}

@ -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<String, OkHttpClient> 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))
}

@ -1,7 +1,7 @@
package io.legado.app.lib.webdav 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.await
import io.legado.app.help.http.okHttpClient
import okhttp3.* import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
@ -113,7 +113,7 @@ class WebDav(urlStr: String) {
request.header("Authorization", Credentials.basic(it.user, it.pass)) request.header("Authorization", Credentials.basic(it.user, it.pass))
} }
request.header("Depth", if (depth < 0) "infinity" else depth.toString()) 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 return null
} }
@ -227,7 +227,7 @@ class WebDav(urlStr: String) {
HttpAuth.auth?.let { HttpAuth.auth?.let {
requestBuilder.header("Authorization", Credentials.basic(it.user, it.pass)) 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 return response.isSuccessful
} }
@ -239,7 +239,7 @@ class WebDav(urlStr: String) {
val requestBuilder = Request.Builder() val requestBuilder = Request.Builder()
.url(url) .url(url)
.addHeader("Authorization", Credentials.basic(auth.user, auth.pass)) .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() .body?.byteStream()
} }
return null return null

@ -312,14 +312,14 @@ class AnalyzeUrl(
if (fieldMap.isNotEmpty() || body.isNullOrBlank()) { if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
RxHttp.postForm(url) RxHttp.postForm(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAllEncoded(fieldMap) .addAllEncoded(fieldMap)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toStrResponse().await() .toStrResponse().await()
} else { } else {
RxHttp.postJson(url) RxHttp.postJson(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAll(body) .addAll(body)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toStrResponse().await() .toStrResponse().await()
@ -327,7 +327,7 @@ class AnalyzeUrl(
} }
else -> RxHttp.get(url) else -> RxHttp.get(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAllEncoded(fieldMap) .addAllEncoded(fieldMap)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toStrResponse().await() .toStrResponse().await()
@ -341,14 +341,14 @@ class AnalyzeUrl(
if (fieldMap.isNotEmpty() || body.isNullOrBlank()) { if (fieldMap.isNotEmpty() || body.isNullOrBlank()) {
RxHttp.postForm(url) RxHttp.postForm(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAllEncoded(fieldMap) .addAllEncoded(fieldMap)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toByteArray().await() .toByteArray().await()
} else { } else {
RxHttp.postJson(url) RxHttp.postJson(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAll(body) .addAll(body)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toByteArray().await() .toByteArray().await()
@ -356,7 +356,7 @@ class AnalyzeUrl(
} }
else -> RxHttp.get(url) else -> RxHttp.get(url)
.setAssemblyEnabled(false) .setAssemblyEnabled(false)
.setOkClient(HttpHelper.getProxyClient(proxy)) .setOkClient(OkHttpHelper.getProxyClient(proxy))
.addAllEncoded(fieldMap) .addAllEncoded(fieldMap)
.addAllHeader(headerMap) .addAllHeader(headerMap)
.toByteArray().await() .toByteArray().await()

Loading…
Cancel
Save