mirror of
https://github.com/tursom/TursomServer.git
synced 2025-04-15 05:50:46 +08:00
update
This commit is contained in:
parent
5209651184
commit
f67c39ac88
ts-core
ts-web/ts-web-netty/src/main/kotlin/cn/tursom/web/netty
@ -10,9 +10,9 @@ dependencies {
|
||||
api(project(":ts-core:ts-buffer"))
|
||||
implementation(project(":ts-core:ts-xml"))
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.1")
|
||||
api(group = "com.squareup.retrofit2", name = "converter-gson", version = "2.9.0")
|
||||
// https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit
|
||||
api(group = "com.squareup.retrofit2", name = "retrofit", version = "2.9.0")
|
||||
compileOnly("com.squareup.okhttp3:okhttp:4.9.1")
|
||||
//api(group = "com.squareup.retrofit2", name = "converter-gson", version = "2.9.0")
|
||||
//api(group = "com.squareup.retrofit2", name = "retrofit", version = "2.9.0")
|
||||
|
||||
// https://mvnrepository.com/artifact/org.jsoup/jsoup
|
||||
api(group = "org.jsoup", name = "jsoup", version = "1.14.2")
|
||||
|
@ -1,23 +0,0 @@
|
||||
package cn.tursom.http
|
||||
|
||||
import retrofit2.Call
|
||||
import retrofit2.CallAdapter
|
||||
import retrofit2.Retrofit
|
||||
import java.lang.reflect.Type
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
object BlockingCallAdapterFactory : CallAdapter.Factory() {
|
||||
override fun get(
|
||||
returnType: Type,
|
||||
annotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): CallAdapter<out Any?, out Any?>? {
|
||||
if (getRawType(returnType) == Call::class.java) return null
|
||||
if (getRawType(returnType) == CompletableFuture::class.java) return null
|
||||
if (annotations.any { it is retrofit2.SkipCallbackExecutor }) return null
|
||||
return object : CallAdapter<Any?, Any?> {
|
||||
override fun responseType(): Type = returnType
|
||||
override fun adapt(call: Call<Any?>): Any? = call.execute().body()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package cn.tursom.http
|
||||
|
||||
import cn.tursom.core.isInheritanceFrom
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Node
|
||||
import retrofit2.Converter
|
||||
import retrofit2.Retrofit
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object HtmlConverterFactory : Converter.Factory() {
|
||||
override fun responseBodyConverter(
|
||||
type: Type,
|
||||
annotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<ResponseBody, out Node>? {
|
||||
return if (type is Class<*> && Document::class.java.isInheritanceFrom(type)) {
|
||||
DocumentResponseBodyConverter(retrofit.baseUrl().uri().toString())
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun requestBodyConverter(
|
||||
type: Type,
|
||||
parameterAnnotations: Array<Annotation>,
|
||||
methodAnnotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<in Node, RequestBody>? {
|
||||
return if (type is Class<*> && type::class.java.isInheritanceFrom(Node::class.java)) {
|
||||
NodeRequestBodyConverter
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentResponseBodyConverter(
|
||||
private val baseUri: String
|
||||
) : Converter<ResponseBody, Document> {
|
||||
override fun convert(value: ResponseBody): Document {
|
||||
return Jsoup.parse(value.string(), baseUri)
|
||||
}
|
||||
}
|
||||
|
||||
object NodeRequestBodyConverter : Converter<Node, RequestBody> {
|
||||
override fun convert(value: Node): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("text/html; charset=utf-8"), value.outerHtml())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,175 +0,0 @@
|
||||
package cn.tursom.http
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.HeapByteBuffer
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
import java.util.zip.GZIPInputStream
|
||||
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
object HttpRequest {
|
||||
val defaultHeader = mapOf(
|
||||
"accept" to "*/*",
|
||||
"connection" to "Keep-Alive",
|
||||
"user-agent" to "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)",
|
||||
"Accept-Encoding" to "gzip, deflate, sdch, br"
|
||||
)
|
||||
|
||||
fun URLConnection.getCharset(): Charset {
|
||||
val contentType = getHeaderField("content-type")
|
||||
return if (contentType == null) {
|
||||
Charsets.UTF_8
|
||||
} else {
|
||||
val startIndex = contentType.indexOf("charset=", ignoreCase = true) + 8
|
||||
if (startIndex < 8) {
|
||||
Charsets.UTF_8
|
||||
} else {
|
||||
var endIndex = contentType.indexOf(";", startIndex = startIndex, ignoreCase = true)
|
||||
if (endIndex < 0) endIndex = contentType.length
|
||||
if (startIndex == endIndex) {
|
||||
Charsets.UTF_8
|
||||
} else {
|
||||
Charset.forName(contentType.substring(startIndex, endIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun URLConnection.getRealInputStream(): InputStream {
|
||||
return if (getHeaderField("content-encoding")?.contains("gzip", true) == true) {
|
||||
GZIPInputStream(inputStream)
|
||||
} else {
|
||||
inputStream
|
||||
}
|
||||
}
|
||||
|
||||
fun send(
|
||||
method: String = "GET",
|
||||
url: String,
|
||||
headers: Map<String, String> = defaultHeader,
|
||||
data: ByteBuffer? = null
|
||||
): HttpURLConnection {
|
||||
val realUrl = URL(url)
|
||||
val conn = realUrl.openConnection() as HttpURLConnection
|
||||
headers.forEach { (key, value) ->
|
||||
conn.setRequestProperty(key, value)
|
||||
}
|
||||
if (data != null) conn.doOutput = true
|
||||
conn.doInput = true
|
||||
conn.requestMethod = method
|
||||
|
||||
data?.let {
|
||||
conn.outputStream.use { out ->
|
||||
data.writeTo(out)
|
||||
out.flush()
|
||||
}
|
||||
}
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
fun send(
|
||||
method: String = "GET",
|
||||
url: String,
|
||||
headers: Map<String, String> = defaultHeader,
|
||||
data: ByteArray?
|
||||
) = send(method, url, headers, data?.let { HeapByteBuffer(data) })
|
||||
|
||||
fun getContextStream(
|
||||
method: String = "GET",
|
||||
url: String,
|
||||
headers: Map<String, String> = defaultHeader,
|
||||
data: ByteBuffer? = null
|
||||
): InputStream = send(method, url, headers, data).inputStream
|
||||
|
||||
fun getContext(
|
||||
method: String = "GET",
|
||||
url: String,
|
||||
headers: Map<String, String> = defaultHeader,
|
||||
data: ByteBuffer? = null
|
||||
) = send(method, url, headers, data).getRealInputStream().readBytes()
|
||||
|
||||
fun getContextStr(
|
||||
method: String = "GET",
|
||||
url: String,
|
||||
headers: Map<String, String> = defaultHeader,
|
||||
data: ByteBuffer? = null
|
||||
): String {
|
||||
val conn = send(method, url, headers, data)
|
||||
return conn.getRealInputStream().readBytes().toString(conn.getCharset())
|
||||
}
|
||||
|
||||
fun doGet(
|
||||
url: String,
|
||||
param: String? = null,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): String = getContextStr(
|
||||
"GET", if (param != null) {
|
||||
"$url?$param"
|
||||
} else {
|
||||
url
|
||||
}, headers
|
||||
)
|
||||
|
||||
infix operator fun get(url: String): String = doGet(url, null)
|
||||
|
||||
fun doGet(
|
||||
url: String,
|
||||
param: Map<String, String>,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): String {
|
||||
val paramSB = StringBuilder()
|
||||
return doGet(url, run {
|
||||
param.forEach {
|
||||
paramSB.append("${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}&")
|
||||
}
|
||||
if (paramSB.isNotEmpty()) paramSB.deleteCharAt(paramSB.lastIndex)
|
||||
paramSB.toString()
|
||||
}, headers)
|
||||
}
|
||||
|
||||
fun doPost(
|
||||
url: String,
|
||||
data: ByteArray,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): String = getContextStr("POST", url, headers, HeapByteBuffer(data))
|
||||
|
||||
fun doPost(
|
||||
url: String,
|
||||
param: Map<String, String>,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): String {
|
||||
val sb = StringBuilder()
|
||||
param.forEach { (key, value) ->
|
||||
sb.append("${URLEncoder.encode(key, "utf-8")}=${URLEncoder.encode(value, "utf-8")}&")
|
||||
}
|
||||
if (sb.isNotEmpty()) sb.deleteCharAt(sb.lastIndex)
|
||||
return doPost(url, sb.toString().toByteArray(), headers)
|
||||
}
|
||||
|
||||
fun doHead(
|
||||
url: String,
|
||||
param: String,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): Map<String, List<String>> = send("HEAD", "$url?$param", headers).headerFields
|
||||
|
||||
fun doHead(
|
||||
url: String,
|
||||
param: Map<String, String>,
|
||||
headers: Map<String, String> = defaultHeader
|
||||
): Map<String, List<String>> {
|
||||
val paramSB = StringBuilder()
|
||||
return doHead(url, run {
|
||||
param.forEach {
|
||||
paramSB.append("${URLEncoder.encode(it.key, "UTF-8")}=${URLEncoder.encode(it.value, "UTF-8")}&")
|
||||
}
|
||||
if (paramSB.isNotEmpty()) paramSB.deleteCharAt(paramSB.lastIndex)
|
||||
paramSB.toString()
|
||||
}, headers)
|
||||
}
|
||||
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package cn.tursom.http
|
||||
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Converter
|
||||
import retrofit2.Retrofit
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object StringConverterFactory : Converter.Factory() {
|
||||
override fun responseBodyConverter(
|
||||
type: Type,
|
||||
annotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<ResponseBody, *>? {
|
||||
return if (type == String::class.java) {
|
||||
StringResponseBodyConverter
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun requestBodyConverter(
|
||||
type: Type,
|
||||
parameterAnnotations: Array<Annotation>,
|
||||
methodAnnotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<*, RequestBody>? {
|
||||
return if (type == String::class.java) {
|
||||
StringRequestBodyConverter
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
object StringResponseBodyConverter : Converter<ResponseBody, String> {
|
||||
override fun convert(value: ResponseBody): String? {
|
||||
return value.string()
|
||||
}
|
||||
}
|
||||
|
||||
object StringRequestBodyConverter : Converter<String, RequestBody> {
|
||||
override fun convert(value: String): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), value)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package cn.tursom.http
|
||||
|
||||
import cn.tursom.core.isInheritanceFrom
|
||||
import cn.tursom.core.xml.Xml
|
||||
import okhttp3.MediaType
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.ResponseBody
|
||||
import org.dom4j.Document
|
||||
import org.dom4j.Node
|
||||
import retrofit2.Converter
|
||||
import retrofit2.Retrofit
|
||||
import java.lang.reflect.Type
|
||||
|
||||
object XmlConverterFactory : Converter.Factory() {
|
||||
override fun responseBodyConverter(
|
||||
type: Type,
|
||||
annotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<ResponseBody, out Node>? {
|
||||
return if (type is Class<*> && Document::class.java.isInheritanceFrom(type)) {
|
||||
DocumentResponseBodyConverter
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun requestBodyConverter(
|
||||
type: Type,
|
||||
parameterAnnotations: Array<Annotation>,
|
||||
methodAnnotations: Array<Annotation>,
|
||||
retrofit: Retrofit
|
||||
): Converter<in Node, RequestBody>? {
|
||||
return if (type is Class<*> && type.isInheritanceFrom(Node::class.java)) {
|
||||
NodeRequestBodyConverter
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
object DocumentResponseBodyConverter : Converter<ResponseBody, Document> {
|
||||
override fun convert(value: ResponseBody): Document {
|
||||
return Xml.saxReader.read(value.string().reader())
|
||||
}
|
||||
}
|
||||
|
||||
object NodeRequestBodyConverter : Converter<Node, RequestBody> {
|
||||
override fun convert(value: Node): RequestBody {
|
||||
return RequestBody.create(MediaType.parse("text/xml; charset=utf-8"), value.asXML())
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cn.tursom.utils
|
||||
package cn.tursom.http.client
|
||||
|
||||
import okhttp3.*
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.InetSocketAddress
|
||||
@ -11,7 +12,6 @@ import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
object AsyncHttpRequest {
|
||||
val defaultClient: OkHttpClient = OkHttpClient().newBuilder()
|
||||
@ -106,7 +106,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient = defaultClient
|
||||
) = post(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), body),
|
||||
RequestBody.create("text/plain;charset=utf-8".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -118,7 +118,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient = defaultClient
|
||||
) = post(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("application/octet-stream"), body),
|
||||
RequestBody.create("application/octet-stream".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -130,7 +130,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient = defaultClient
|
||||
) = post(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("application/octet-stream"), body),
|
||||
RequestBody.create("application/octet-stream".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -151,7 +151,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient
|
||||
): String {
|
||||
val response = get(url, param, headers, client)
|
||||
return response.body()!!.string()
|
||||
return response.body!!.string()
|
||||
}
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
@ -160,7 +160,7 @@ object AsyncHttpRequest {
|
||||
body: RequestBody,
|
||||
headers: Map<String, String>? = null,
|
||||
client: OkHttpClient
|
||||
): String = post(url, body, headers, client).body()!!.string()
|
||||
): String = post(url, body, headers, client).body!!.string()
|
||||
|
||||
suspend fun postStr(
|
||||
url: String,
|
||||
@ -196,7 +196,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient
|
||||
): String = postStr(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), body),
|
||||
RequestBody.create("text/plain;charset=utf-8".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -215,7 +215,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient
|
||||
): String = postStr(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("application/octet-stream"), body),
|
||||
RequestBody.create("application/octet-stream".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -237,7 +237,7 @@ object AsyncHttpRequest {
|
||||
param: Map<String, String>? = null,
|
||||
headers: Map<String, String>? = null,
|
||||
client: OkHttpClient
|
||||
): ByteArray = get(url, param, headers, client).body()!!.bytes()
|
||||
): ByteArray = get(url, param, headers, client).body!!.bytes()
|
||||
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
@ -246,7 +246,7 @@ object AsyncHttpRequest {
|
||||
body: RequestBody,
|
||||
headers: Map<String, String>? = null,
|
||||
client: OkHttpClient
|
||||
): ByteArray = post(url, body, headers, client).body()!!.bytes()
|
||||
): ByteArray = post(url, body, headers, client).body!!.bytes()
|
||||
|
||||
|
||||
suspend fun postByteArray(
|
||||
@ -291,7 +291,7 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient
|
||||
): ByteArray = postByteArray(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), body),
|
||||
RequestBody.create("text/plain;charset=utf-8".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
@ -314,8 +314,8 @@ object AsyncHttpRequest {
|
||||
client: OkHttpClient
|
||||
): ByteArray = postByteArray(
|
||||
url,
|
||||
RequestBody.create(MediaType.parse("application/octet-stream"), body),
|
||||
RequestBody.create("application/octet-stream".toMediaTypeOrNull(), body),
|
||||
headers,
|
||||
client
|
||||
)
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ dependencies {
|
||||
api(project(":ts-core:ts-buffer"))
|
||||
api(project(":ts-core:ts-log"))
|
||||
compileOnly(project(":ts-socket"))
|
||||
api(group = "io.netty", name = "netty-all", version = "4.1.67.Final")
|
||||
api(group = "io.netty", name = "netty-all", version = nettyVersion)
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,8 +150,10 @@ open class NettyHttpContent(
|
||||
if (log.traceEnabled) {
|
||||
log?.trace("write {}", message)
|
||||
}
|
||||
getResponseBodyBuf().addComponent(Unpooled.wrappedBuffer(message.toByteArray()))
|
||||
//responseBody.write(message.toByteArray())
|
||||
val compositeByteBuf = getResponseBodyBuf()
|
||||
val bytes = message.toByteArray()
|
||||
compositeByteBuf.addComponent(Unpooled.wrappedBuffer(bytes))
|
||||
compositeByteBuf.writerIndex(compositeByteBuf.writerIndex() + bytes.size)
|
||||
}
|
||||
|
||||
override fun write(byte: Byte) {
|
||||
|
@ -0,0 +1,17 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import io.netty.channel.ChannelHandler
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.handler.timeout.TimeoutException
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
object TimeoutHandler : ChannelHandler {
|
||||
override fun handlerAdded(ctx: ChannelHandlerContext?) {}
|
||||
override fun handlerRemoved(ctx: ChannelHandlerContext?) {}
|
||||
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable?) {
|
||||
when (cause) {
|
||||
is TimeoutException -> ctx.close()
|
||||
else -> ctx.fireExceptionCaught(cause)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user