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. 13
      app/src/main/java/io/legado/app/help/http/OkHttpHelper.kt
  3. 85
      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 package io.legado.app.help.http
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Request
import okhttp3.Response
import kotlin.coroutines.resume import kotlin.coroutines.resume
@Suppress("unused") @Suppress("unused")
object HttpHelper { 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 = suspend fun ajax(params: AjaxWebView.AjaxParams): StrResponse =
suspendCancellableCoroutine { block -> suspendCancellableCoroutine { block ->
val webView = AjaxWebView() val webView = AjaxWebView()

@ -13,6 +13,10 @@ import java.util.concurrent.TimeUnit
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException import kotlin.coroutines.resumeWithException
private val proxyClientCache: ConcurrentHashMap<String, OkHttpClient> by lazy {
ConcurrentHashMap()
}
val okHttpClient: OkHttpClient by lazy { val okHttpClient: OkHttpClient by lazy {
val specs = arrayListOf( val specs = arrayListOf(
@ -44,11 +48,6 @@ val okHttpClient: OkHttpClient by lazy {
builder.build() builder.build()
} }
object OkHttpHelper {
private val proxyClientCache: ConcurrentHashMap<String, OkHttpClient> by lazy {
ConcurrentHashMap()
}
/** /**
* 缓存代理okHttp * 缓存代理okHttp
*/ */
@ -92,6 +91,10 @@ object OkHttpHelper {
} }
return okHttpClient 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 -> suspend fun Call.await(): Response = suspendCancellableCoroutine { block ->

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

Loading…
Cancel
Save