pull/977/head
gedoor 4 years ago
parent 9e029a6823
commit ccb4a0092f
  1. 8
      app/src/main/java/io/legado/app/help/http/HttpHelper.kt
  2. 89
      app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt
  3. 109
      app/src/main/java/io/legado/app/lib/webdav/WebDav.kt
  4. 12
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt

@ -1,19 +1,11 @@
package io.legado.app.help.http
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Request
import okhttp3.Response
import kotlin.coroutines.resume
@Suppress("unused")
object HttpHelper {
suspend fun newCall(builder: Request.Builder.() -> Unit, proxy: String? = null): Response {
val client = OkHttpHelper.getProxyClient(proxy)
val requestBuilder = Request.Builder().apply(builder)
return client.newCall(requestBuilder.build()).await()
}
suspend fun ajax(params: AjaxWebView.AjaxParams): StrResponse =
suspendCancellableCoroutine { block ->
val webView = AjaxWebView()

@ -13,6 +13,10 @@ import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
private val proxyClientCache: ConcurrentHashMap<String, OkHttpClient> by lazy {
ConcurrentHashMap()
}
val okHttpClient: OkHttpClient by lazy {
val specs = arrayListOf(
@ -44,54 +48,53 @@ val okHttpClient: OkHttpClient by lazy {
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
}
/**
* 缓存代理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]
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 (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()
}
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
val proxyClient = builder.build()
proxyClientCache[proxy] = proxyClient
return proxyClient
}
return okHttpClient
}
fun OkHttpClient.newCall(builder: Request.Builder.() -> Unit): Call {
val requestBuilder = Request.Builder().apply(builder)
return this.newCall(requestBuilder.build())
}
suspend fun Call.await(): Response = suspendCancellableCoroutine { block ->

@ -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.newCall
import io.legado.app.help.http.okHttpClient
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
@ -21,17 +21,19 @@ class WebDav(urlStr: String) {
companion object {
// 指定返回哪些属性
private const val DIR =
"""<?xml version="1.0"?>
<a:propfind xmlns:a="DAV:">
<a:prop>
<a:displayname/>
<a:resourcetype/>
<a:getcontentlength/>
<a:creationdate/>
<a:getlastmodified/>
%s
</a:prop>
</a:propfind>"""
"""
<?xml version="1.0"?>
<a:propfind xmlns:a="DAV:">
<a:prop>
<a:displayname/>
<a:resourcetype/>
<a:getcontentlength/>
<a:creationdate/>
<a:getlastmodified/>
%s
</a:prop>
</a:propfind>
"""
}
private val url: URL = URL(urlStr)
@ -92,7 +94,7 @@ class WebDav(urlStr: String) {
}
@Throws(IOException::class)
private suspend fun propFindResponse(propsList: ArrayList<String>, depth: Int = 1): Response? {
private suspend fun propFindResponse(propsList: ArrayList<String>): Response? {
val requestProps = StringBuilder()
for (p in propsList) {
requestProps.append("<a:").append(p).append("/>\n")
@ -102,19 +104,17 @@ class WebDav(urlStr: String) {
} else {
String.format(DIR, requestProps.toString() + "\n")
}
httpUrl?.let { url ->
// 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性
// 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。
val requestBody = requestPropsStr.toRequestBody("text/plain".toMediaType())
val request = Request.Builder()
.url(url)
.method("PROPFIND", requestBody)
HttpAuth.auth?.let {
request.header("Authorization", Credentials.basic(it.user, it.pass))
}
request.header("Depth", if (depth < 0) "infinity" else depth.toString())
return okHttpClient.newCall(request.build()).await()
val url = httpUrl
val auth = HttpAuth.auth
if (url != null && auth != null) {
return okHttpClient.newCall {
url(url)
addHeader("Authorization", Credentials.basic(auth.user, auth.pass))
// 添加RequestBody对象,可以只返回的属性。如果设为null,则会返回全部属性
// 注意:尽量手动指定需要返回的属性。若返回全部属性,可能后由于Prop.java里没有该属性名,而崩溃。
val requestBody = requestPropsStr.toRequestBody("text/plain".toMediaType())
method("PROPFIND", requestBody)
}.await()
}
return null
}
@ -159,11 +159,14 @@ class WebDav(urlStr: String) {
* @return 是否创建成功
*/
suspend fun makeAsDir(): Boolean {
httpUrl?.let { url ->
val request = Request.Builder()
.url(url)
.method("MKCOL", null)
return execRequest(request)
val url = httpUrl
val auth = HttpAuth.auth
if (url != null && auth != null) {
return okHttpClient.newCall {
url(url)
method("MKCOL", null)
addHeader("Authorization", Credentials.basic(auth.user, auth.pass))
}.await().isSuccessful
}
return false
}
@ -197,11 +200,14 @@ class WebDav(urlStr: String) {
if (!file.exists()) return false
// 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息
val fileBody = file.asRequestBody(contentType?.toMediaType())
httpUrl?.let {
val request = Request.Builder()
.url(it)
.put(fileBody)
return execRequest(request)
val url = httpUrl
val auth = HttpAuth.auth
if (url != null && auth != null) {
return okHttpClient.newCall {
url(url)
put(fileBody)
addHeader("Authorization", Credentials.basic(auth.user, auth.pass))
}.await().isSuccessful
}
return false
}
@ -209,38 +215,27 @@ class WebDav(urlStr: String) {
suspend fun upload(byteArray: ByteArray, contentType: String? = null): Boolean {
// 务必注意RequestBody不要嵌套,不然上传时内容可能会被追加多余的文件信息
val fileBody = byteArray.toRequestBody(contentType?.toMediaType())
httpUrl?.let {
val request = Request.Builder()
.url(it)
.put(fileBody)
return execRequest(request)
val url = httpUrl
val auth = HttpAuth.auth
if (url != null && auth != null) {
return okHttpClient.newCall {
url(url)
put(fileBody)
addHeader("Authorization", Credentials.basic(auth.user, auth.pass))
}.await().isSuccessful
}
return false
}
/**
* 执行请求获取响应结果
* @param requestBuilder 因为还需要追加验证信息所以此处传递Request.Builder的对象而不是Request的对象
* @return 请求执行的结果
*/
@Throws(IOException::class)
private suspend fun execRequest(requestBuilder: Request.Builder): Boolean {
HttpAuth.auth?.let {
requestBuilder.header("Authorization", Credentials.basic(it.user, it.pass))
}
val response = okHttpClient.newCall(requestBuilder.build()).await()
return response.isSuccessful
}
@Throws(IOException::class)
private suspend fun getInputStream(): InputStream? {
val url = httpUrl
val auth = HttpAuth.auth
if (url != null && auth != null) {
return HttpHelper.newCall({
return okHttpClient.newCall {
url(url)
addHeader("Authorization", Credentials.basic(auth.user, auth.pass))
}).body?.byteStream()
}.await().body?.byteStream()
}
return null
}

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

Loading…
Cancel
Save