httpserver

This commit is contained in:
lushunming 2025-07-21 15:24:56 +08:00
parent 7e65d5eae0
commit b5a1f6ef04
5 changed files with 73 additions and 62 deletions

View File

@ -86,10 +86,10 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1"
// https://mvnrepository.com/artifact/com.sun.net.httpserver/http
// implementation("com.sun.net.httpserver:http:20070405")
implementation(files("libs/sun-common-server.jar"))
implementation("com.sun.net.httpserver:http:20070405")
// implementation("com.hibegin:simplewebserver:0.1.15")
implementation("com.github.codeborne.klite:klite-server:1.7.0")
//implementation("com.github.codeborne.klite:klite-server:1.7.0")
//implementation 'wang.harlon.quickjs:wrapper-java:1.0.0'

View File

@ -1,10 +1,17 @@
package com.github.catvod.utils
import com.github.catvod.crawler.SpiderDebug
import com.github.catvod.net.OkHttp
import com.google.gson.Gson
import klite.Server
import com.sun.net.httpserver.HttpExchange
import com.sun.net.httpserver.HttpServer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import java.io.BufferedOutputStream
import java.io.OutputStreamWriter
import java.net.InetSocketAddress
import java.nio.charset.Charset
@ -13,59 +20,75 @@ object ProxyServer {
private val THREAD_NUM = Runtime.getRuntime().availableProcessors() * 2
private const val partSize = 1024 * 1024 * 1
private var port = 12345
private var server: Server? = null
private var httpServer: HttpServer? = null
private val infos = mutableMapOf<String, MutableMap<String, MutableList<String>>>();
fun stop() {
server?.stop(1000)
httpServer?.stop(1_000)
}
fun start() {
try {
server = Server(InetSocketAddress(port)).apply {
context("/api") {
get("/hello") { "Hello, world!" }
httpServer = HttpServer.create(InetSocketAddress(port), 100);
httpServer?.createContext("/") { httpExchange ->
run {
httpExchange.sendResponseHeaders(200, "server running ".length.toLong());
val os = httpExchange.responseBody
val writer = OutputStreamWriter(os, Charset.defaultCharset())
writer.write("server running ")
writer.close()
os.close()
httpExchange.close()
}
start()
}
httpServer?.createContext("/proxy") { httpExchange ->
run {
val params = queryToMap(httpExchange.requestURI.query)
val url = Util.base64Decode(params?.get("url"))
val header: Map<String, String> = Gson().fromJson<Map<String, String>>(
Util.base64Decode(params?.get("headers")), MutableMap::class.java
)
CoroutineScope(Dispatchers.IO).launch {
proxyAsync(
url, header, httpExchange
)
}
}
}
httpServer?.executor = null;
httpServer?.start();
} catch (e: Exception) {
SpiderDebug.log("start server e:" + e.message)
e.printStackTrace()
stop()
httpServer?.stop(1000)
}
SpiderDebug.log("Server start on " + port)
port = httpServer?.address?.port!!
SpiderDebug.log("ktorServer start on " + port)
}
/*class ProxyController : Controller() {
fun index() {
val url = Util.base64Decode(getRequest().getParaToStr("url"))
val header: Map<String, String> = Gson().fromJson<Map<String, String>>(
Util.base64Decode(getRequest().getParaToStr("headers")), MutableMap::class.java
)
CoroutineScope(Dispatchers.IO).launch {
proxyAsync(
url, header, getRequest(), getResponse()
)
}
}
}
private suspend fun proxyAsync(
url: String, headers: Map<String, String>, request: HttpRequest, response: HttpResponse
url: String, headers: Map<String, String>, httpExchange: HttpExchange
) {
val channels = List(THREAD_NUM) { Channel<ByteArray>() }
var outputStream = ByteArrayOutputStream()
val outputStream = httpExchange.responseBody
val bufferedOutputStream = BufferedOutputStream(outputStream)
try {
SpiderDebug.log("--proxyMultiThread: THREAD_NUM: $THREAD_NUM")
var rangeHeader = request.getHeader("Range")
var rangeHeader = httpExchange.requestHeaders.getFirst("Range")
//没有range头
if (rangeHeader.isNullOrEmpty()) {
// 处理初始请求
@ -92,22 +115,15 @@ object ProxyServer {
SpiderDebug.log("contentLength: $contentLength")
val finalEndPoint = if (endPoint == -1L) contentLength - 1 else endPoint
response.addHeader("Connection", "keep-alive")
response.addHeader("Content-Length", (finalEndPoint - startPoint + 1).toString())
response.addHeader("Content-Range", "bytes $startPoint-$finalEndPoint/$contentLength")
response.addHeader("Content-Type", info["Content-Type"]?.get(0))
val statusCode = 206
val sb = StringBuilder();
sb.append("HTTP/1.1 ").append(" ").append(statusCode).append(" ")
.append(StatusCodeUtil.getStatusCode(statusCode)).append("\r\n")
for ((key, value) in response.header) {
sb.append(key).append(": ").append(value).append("\r\n")
httpExchange.responseHeaders.apply {
set("Connection", "keep-alive")
set("Content-Length", (finalEndPoint - startPoint + 1).toString())
set("Content-Range", "bytes $startPoint-$finalEndPoint/$contentLength")
set("Content-Type", info["Content-Type"]?.get(0))
}
sb.append("\r\n")
outputStream.write(sb.toString().toByteArray(Charset.defaultCharset()))
outputStream.flush()
response.send(outputStream, false)
httpExchange.sendResponseHeaders(206, 0)
// 使用流式响应
var currentStart = startPoint
@ -122,9 +138,7 @@ object ProxyServer {
for (i in 0 until THREAD_NUM) {
if (currentStart > finalEndPoint) {
break
}
if (currentStart > finalEndPoint) break
val chunkStart = currentStart
val chunkEnd = minOf(currentStart + partSize - 1, finalEndPoint)
producerJob += CoroutineScope(Dispatchers.IO).launch {
@ -139,30 +153,27 @@ object ProxyServer {
val data = channels[index].receive()
SpiderDebug.log("Received chunk: ${data.size} bytes")
outputStream = ByteArrayOutputStream();
outputStream.write(data);
outputStream.flush()
response.send(outputStream, false)
// bufferedOutputStream.close()
bufferedOutputStream.write(data)
bufferedOutputStream.flush()
}
}
response.send(ByteArrayOutputStream(), true)
} catch (e: Exception) {
SpiderDebug.log("error: ${e.message}")
e.printStackTrace()
outputStream.write("error: ${e.message}".toByteArray())
} finally {
channels.forEach { it.close() }
bufferedOutputStream.close()
outputStream.close()
httpExchange.close()
}
}
*/
private fun queryToMap(query: String?): Map<String, String>? {
if (query == null) {
return null

Binary file not shown.

View File

@ -1 +1 @@
46a0bc151a572484c98dc163e9b944dd
822127bc7ad6da1d93a4ef9f8b9f15a1

View File

@ -1,5 +1,5 @@
{
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThreadNew/jar/custom_spider.jar;md5;46a0bc151a572484c98dc163e9b944dd",
"spider": "https://gh.llkk.cc/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThreadNew/jar/custom_spider.jar;md5;822127bc7ad6da1d93a4ef9f8b9f15a1",
"lives": [
{
"name": "电视直播",