fetch太慢去除历史提交记录

This commit is contained in:
gedoor committed 2022-01-03 23:59:44 +08:00
commit 51c16a1efc
1294 files changed
+194322

No files matched your search

@@ -0,0 +1,102 @@
package io.legado.app.web
import android.graphics.Bitmap
import com.google.gson.Gson
import fi.iki.elonen.NanoHTTPD
import io.legado.app.api.ReturnData
import io.legado.app.api.controller.BookController
import io.legado.app.api.controller.BookSourceController
import io.legado.app.api.controller.RssSourceController
import io.legado.app.web.utils.AssetsWeb
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.util.*
class HttpServer(port: Int) : NanoHTTPD(port) {
private val assetsWeb = AssetsWeb("web")
override fun serve(session: IHTTPSession): Response {
var returnData: ReturnData? = null
val ct = ContentType(session.headers["content-type"]).tryUTF8()
session.headers["content-type"] = ct.contentTypeHeader
var uri = session.uri
try {
when (session.method) {
Method.OPTIONS -> {
val response = newFixedLengthResponse("")
response.addHeader("Access-Control-Allow-Methods", "POST")
response.addHeader("Access-Control-Allow-Headers", "content-type")
response.addHeader("Access-Control-Allow-Origin", session.headers["origin"])
//response.addHeader("Access-Control-Max-Age", "3600");
return response
}
Method.POST -> {
val files = HashMap<String, String>()
session.parseBody(files)
val postData = files["postData"]
returnData = when (uri) {
"/saveBookSource" -> BookSourceController.saveSource(postData)
"/saveBookSources" -> BookSourceController.saveSources(postData)
"/deleteBookSources" -> BookSourceController.deleteSources(postData)
"/saveBook" -> BookController.saveBook(postData)
"/addLocalBook" -> BookController.addLocalBook(session.parameters)
"/saveRssSource" -> RssSourceController.saveSource(postData)
"/saveRssSources" -> RssSourceController.saveSources(postData)
"/deleteRssSources" -> RssSourceController.deleteSources(postData)
else -> null
}
}
Method.GET -> {
val parameters = session.parameters
returnData = when (uri) {
"/getBookSource" -> BookSourceController.getSource(parameters)
"/getBookSources" -> BookSourceController.sources
"/getBookshelf" -> BookController.bookshelf
"/getChapterList" -> BookController.getChapterList(parameters)
"/refreshToc" -> BookController.refreshToc(parameters)
"/getBookContent" -> BookController.getBookContent(parameters)
"/cover" -> BookController.getCover(parameters)
"/getRssSource" -> RssSourceController.getSource(parameters)
"/getRssSources" -> RssSourceController.sources
else -> null
}
}
else -> Unit
}
if (returnData == null) {
if (uri.endsWith("/"))
uri += "index.html"
return assetsWeb.getResponse(uri)
}
val response = if (returnData.data is Bitmap) {
val outputStream = ByteArrayOutputStream()
(returnData.data as Bitmap).compress(Bitmap.CompressFormat.PNG, 100, outputStream)
val byteArray = outputStream.toByteArray()
outputStream.close()
val inputStream = ByteArrayInputStream(byteArray)
newFixedLengthResponse(
Response.Status.OK,
"image/png",
inputStream,
byteArray.size.toLong()
)
} else {
newFixedLengthResponse(Gson().toJson(returnData))
}
response.addHeader("Access-Control-Allow-Methods", "GET, POST")
response.addHeader("Access-Control-Allow-Origin", session.headers["origin"])
return response
} catch (e: Exception) {
return newFixedLengthResponse(e.message)
}
}
}
@@ -0,0 +1,5 @@
# web服务
* controller 数据操作
* HttpServer http服务
* WebSocketServer 持续通讯服务
@@ -0,0 +1,20 @@
package io.legado.app.web
import fi.iki.elonen.NanoWSD
import io.legado.app.web.socket.BookSourceDebugWebSocket
import io.legado.app.web.socket.RssSourceDebugWebSocket
class WebSocketServer(port: Int) : NanoWSD(port) {
override fun openWebSocket(handshake: IHTTPSession): WebSocket? {
return when (handshake.uri) {
"/bookSourceDebug" -> {
BookSourceDebugWebSocket(handshake)
}
"/rssSourceDebug" -> {
RssSourceDebugWebSocket(handshake)
}
else -> null
}
}
}
@@ -0,0 +1,95 @@
package io.legado.app.web.socket
import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoWSD
import io.legado.app.R
import io.legado.app.data.appDb
import io.legado.app.model.Debug
import io.legado.app.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import splitties.init.appCtx
import timber.log.Timber
import java.io.IOException
class BookSourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) :
NanoWSD.WebSocket(handshakeRequest),
CoroutineScope by MainScope(),
Debug.Callback {
private val notPrintState = arrayOf(10, 20, 30, 40)
override fun onOpen() {
launch(IO) {
kotlin.runCatching {
while (isOpen) {
ping("ping".toByteArray())
delay(30000)
}
}
}
}
override fun onClose(
code: NanoWSD.WebSocketFrame.CloseCode,
reason: String,
initiatedByRemote: Boolean
) {
cancel()
Debug.cancelDebug(true)
}
override fun onMessage(message: NanoWSD.WebSocketFrame) {
launch(IO) {
kotlin.runCatching {
if (!message.textPayload.isJson()) {
send("数据必须为Json格式")
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
return@launch
}
val debugBean = GSON.fromJsonObject<Map<String, String>>(message.textPayload)
if (debugBean != null) {
val tag = debugBean["tag"]
val key = debugBean["key"]
if (tag.isNullOrBlank() || key.isNullOrBlank()) {
send(appCtx.getString(R.string.cannot_empty))
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
return@launch
}
appDb.bookSourceDao.getBookSource(tag)?.let {
Debug.callback = this@BookSourceDebugWebSocket
Debug.startDebug(this, it, key)
}
}
}
}
}
override fun onPong(pong: NanoWSD.WebSocketFrame) {
}
override fun onException(exception: IOException) {
Debug.cancelDebug(true)
}
override fun printLog(state: Int, msg: String) {
if (state in notPrintState) {
return
}
runOnIO {
runCatching {
send(msg)
if (state == -1 || state == 1000) {
Debug.cancelDebug(true)
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
}
}.onFailure {
Timber.e(it)
}
}
}
}
@@ -0,0 +1,94 @@
package io.legado.app.web.socket
import fi.iki.elonen.NanoHTTPD
import fi.iki.elonen.NanoWSD
import io.legado.app.R
import io.legado.app.data.appDb
import io.legado.app.model.Debug
import io.legado.app.utils.*
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers.IO
import splitties.init.appCtx
import timber.log.Timber
import java.io.IOException
class RssSourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) :
NanoWSD.WebSocket(handshakeRequest),
CoroutineScope by MainScope(),
Debug.Callback {
private val notPrintState = arrayOf(10, 20, 30, 40)
override fun onOpen() {
launch(IO) {
kotlin.runCatching {
while (isOpen) {
ping("ping".toByteArray())
delay(30000)
}
}
}
}
override fun onClose(
code: NanoWSD.WebSocketFrame.CloseCode,
reason: String,
initiatedByRemote: Boolean
) {
cancel()
Debug.cancelDebug(true)
}
override fun onMessage(message: NanoWSD.WebSocketFrame) {
launch(IO) {
kotlin.runCatching {
if (!message.textPayload.isJson()) {
send("数据必须为Json格式")
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
return@launch
}
val debugBean = GSON.fromJsonObject<Map<String, String>>(message.textPayload)
if (debugBean != null) {
val tag = debugBean["tag"]
if (tag.isNullOrBlank()) {
send(appCtx.getString(R.string.cannot_empty))
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
return@launch
}
appDb.rssSourceDao.getByKey(tag)?.let {
Debug.callback = this@RssSourceDebugWebSocket
Debug.startDebug(this, it)
}
}
}
}
}
override fun onPong(pong: NanoWSD.WebSocketFrame) {
}
override fun onException(exception: IOException) {
Debug.cancelDebug(true)
}
override fun printLog(state: Int, msg: String) {
if (state in notPrintState) {
return
}
runOnIO {
runCatching {
send(msg)
if (state == -1 || state == 1000) {
Debug.cancelDebug(true)
close(NanoWSD.WebSocketFrame.CloseCode.NormalClosure, "调试结束", false)
}
}.onFailure {
Timber.e(it)
}
}
}
}
@@ -0,0 +1,44 @@
package io.legado.app.web.utils
import android.content.res.AssetManager
import android.text.TextUtils
import fi.iki.elonen.NanoHTTPD
import splitties.init.appCtx
import java.io.File
import java.io.IOException
class AssetsWeb(rootPath: String) {
private val assetManager: AssetManager = appCtx.assets
private var rootPath = "web"
init {
if (!TextUtils.isEmpty(rootPath)) {
this.rootPath = rootPath
}
}
@Throws(IOException::class)
fun getResponse(path: String): NanoHTTPD.Response {
var path1 = path
path1 = (rootPath + path1).replace("/+".toRegex(), File.separator)
val inputStream = assetManager.open(path1)
return NanoHTTPD.newChunkedResponse(
NanoHTTPD.Response.Status.OK,
getMimeType(path1),
inputStream
)
}
private fun getMimeType(path: String): String {
val suffix = path.substring(path.lastIndexOf("."))
return when {
suffix.equals(".html", ignoreCase = true)
|| suffix.equals(".htm", ignoreCase = true) -> "text/html"
suffix.equals(".js", ignoreCase = true) -> "text/javascript"
suffix.equals(".css", ignoreCase = true) -> "text/css"
suffix.equals(".ico", ignoreCase = true) -> "image/x-icon"
else -> "text/html"
}
}
}