From 7685ca42f5ebbdc558441e87b03b8c464508cee7 Mon Sep 17 00:00:00 2001 From: tursom Date: Wed, 20 May 2020 00:23:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9Http=20Multipart?= =?UTF-8?q?=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/tursom/web/netty/NettyHttpContent.kt | 4 +++- .../cn/tursom/web/netty/NettyHttpHandler.kt | 2 +- .../cn/tursom/web/netty/NettyHttpServer.kt | 5 ++-- .../tursom/web/netty/NettyWebSocketContent.kt | 4 +++- .../main/kotlin/cn/tursom/web/HttpContent.kt | 5 ++-- .../kotlin/cn/tursom/web/WebSocketContent.kt | 2 ++ .../cn/tursom/web/router/RoutedHttpHandler.kt | 13 +++++----- .../cn/tursom/web/utils/EmptyHttpContent.kt | 3 ++- web/web-coroutine/build.gradle | 2 +- .../src/main/kotlin/cn/tursom/web/Utils.kt | 24 +++++++++++++++++++ .../web/router/AsyncRoutedHttpHandler.kt | 2 +- 11 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 web/web-coroutine/src/main/kotlin/cn/tursom/web/Utils.kt diff --git a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpContent.kt b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpContent.kt index 18aeac6..6a231c4 100644 --- a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpContent.kt +++ b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpContent.kt @@ -33,7 +33,7 @@ open class NettyHttpContent( } uri } - override val clientIp get() = ctx.channel().remoteAddress()!! + override val remoteAddress get() = ctx.channel().remoteAddress()!! override val realIp: String = super.realIp val httpMethod: HttpMethod get() = request.method() val protocolVersion: HttpVersion get() = request.protocolVersion() @@ -71,6 +71,8 @@ open class NettyHttpContent( } } + override fun peekBody(): ByteBuffer? = bodyList.peek()?.content()?.let { NettyByteBuffer(it.slice()) } + override fun waitBody(action: (end: Boolean) -> Unit) { if (!requestSendFully) { waitBodyHandler.add(action) diff --git a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpHandler.kt b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpHandler.kt index cdb24eb..e560f48 100644 --- a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpHandler.kt +++ b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpHandler.kt @@ -19,7 +19,7 @@ class NettyHttpHandler( override fun channelRead0(ctx: ChannelHandlerContext, msg: FullHttpRequest) { val handlerContext = NettyHttpContent(ctx, msg) - log?.debug("{} {} {}", handlerContext.clientIp, handlerContext.method, handlerContext.uri) + log?.debug("{} {} {}", handlerContext.remoteAddress, handlerContext.method, handlerContext.uri) handler.handle(handlerContext) } diff --git a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpServer.kt b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpServer.kt index 1cd79d8..803d445 100644 --- a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpServer.kt +++ b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyHttpServer.kt @@ -27,7 +27,7 @@ class NettyHttpServer( var bodySize: Int = 512 * 1024, autoRun: Boolean = false, var webSocketPath: Iterable>> = listOf(), - var readTimeout: Int? = null, + var readTimeout: Int? = 60, var writeTimeout: Int? = null, decodeType: NettyHttpDecodeType = NettyHttpDecodeType.MULTI_PART, backlog: Int = 1024 @@ -37,7 +37,7 @@ class NettyHttpServer( bodySize: Int = 512 * 1024, autoRun: Boolean = false, webSocketPath: Iterable>> = listOf(), - readTimeout: Int? = null, + readTimeout: Int? = 60, writeTimeout: Int? = null, decodeType: NettyHttpDecodeType = NettyHttpDecodeType.MULTI_PART, handler: (content: NettyHttpContent) -> Unit @@ -49,7 +49,6 @@ class NettyHttpServer( bodySize, autoRun, webSocketPath, readTimeout, writeTimeout, decodeType ) - var decodeType: NettyHttpDecodeType = decodeType set(value) { if (value != field) { diff --git a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyWebSocketContent.kt b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyWebSocketContent.kt index e177f04..ae4ccf8 100644 --- a/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyWebSocketContent.kt +++ b/web/netty-web/src/main/kotlin/cn/tursom/web/netty/NettyWebSocketContent.kt @@ -8,10 +8,12 @@ import io.netty.buffer.Unpooled import io.netty.channel.Channel import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame import io.netty.handler.codec.http.websocketx.TextWebSocketFrame +import java.net.SocketAddress class NettyWebSocketContent( - private val channel: Channel + val channel: Channel ) : WebSocketContent { + override val remoteAddress: SocketAddress get() = channel.remoteAddress() override fun writeText(buffer: ByteBuffer) { if (buffer is NettyByteBuffer) { channel.writeAndFlush(TextWebSocketFrame(buffer.byteBuf)) diff --git a/web/src/main/kotlin/cn/tursom/web/HttpContent.kt b/web/src/main/kotlin/cn/tursom/web/HttpContent.kt index a404b75..3850430 100644 --- a/web/src/main/kotlin/cn/tursom/web/HttpContent.kt +++ b/web/src/main/kotlin/cn/tursom/web/HttpContent.kt @@ -15,13 +15,14 @@ interface HttpContent : ResponseHeaderAdapter, RequestHeaderAdapter { var responseCode: Int var responseMessage: String? val body: ByteBuffer? - val clientIp: SocketAddress + val remoteAddress: SocketAddress val method: String val realIp - get() = getHeader("X-Forwarded-For") ?: clientIp.toString().let { str -> + get() = getHeader("X-Forwarded-For") ?: remoteAddress.toString().let { str -> str.substring(1, str.indexOf(':').let { if (it < 1) str.length else it - 1 }) } + fun peekBody(): ByteBuffer? fun waitBody(action: (end: Boolean) -> Unit = { addBodyParam() }) fun addBodyParam(body: ByteBuffer) fun addBodyParam() { diff --git a/web/src/main/kotlin/cn/tursom/web/WebSocketContent.kt b/web/src/main/kotlin/cn/tursom/web/WebSocketContent.kt index 8f25adb..eb79470 100644 --- a/web/src/main/kotlin/cn/tursom/web/WebSocketContent.kt +++ b/web/src/main/kotlin/cn/tursom/web/WebSocketContent.kt @@ -2,9 +2,11 @@ package cn.tursom.web import cn.tursom.core.buffer.ByteBuffer import cn.tursom.core.buffer.impl.HeapByteBuffer +import java.net.SocketAddress import java.nio.charset.Charset interface WebSocketContent { + val remoteAddress: SocketAddress fun writeText(buffer: ByteBuffer) fun writeText(bytes: ByteArray) = writeText(HeapByteBuffer(bytes)) fun writeText(str: String, charset: Charset = Charsets.UTF_8) = writeText(str.toByteArray(charset)) diff --git a/web/src/main/kotlin/cn/tursom/web/router/RoutedHttpHandler.kt b/web/src/main/kotlin/cn/tursom/web/router/RoutedHttpHandler.kt index c8a5f58..3760df1 100644 --- a/web/src/main/kotlin/cn/tursom/web/router/RoutedHttpHandler.kt +++ b/web/src/main/kotlin/cn/tursom/web/router/RoutedHttpHandler.kt @@ -1,7 +1,6 @@ package cn.tursom.web.router import cn.tursom.core.buffer.ByteBuffer -import cn.tursom.core.cast import cn.tursom.core.lambda import cn.tursom.core.regex.regex import cn.tursom.json.JsonWorkerImpl @@ -282,13 +281,13 @@ open class RoutedHttpHandler( fun autoReturn(method: Method, result: Any?, content: HttpContent, doLog: Boolean? = null) { method.getAnnotation(ContextType::class.java)?.let { content.setContextType(it.type.value) - log?.debug("{}: autoReturn context type auto set to {}({})", content.clientIp, it.type.key, it.type.value) + log?.debug("{}: autoReturn context type auto set to {}({})", content.remoteAddress, it.type.key, it.type.value) } autoReturn(result, content, doLog ?: method.doLog) } fun autoReturn(result: Any?, content: HttpContent, doLog: Boolean = true) { - if (doLog) log?.debug("{}: autoReturn: {}", content.clientIp, result) + if (doLog) log?.debug("{}: autoReturn: {}", content.remoteAddress, result) result ?: return when (result) { null -> content.finish(404) @@ -310,7 +309,7 @@ open class RoutedHttpHandler( } fun finishHtml(result: Any?, content: HttpContent, doLog: Boolean = true) { - if (doLog) log?.debug("{} finishHtml {}", content.clientIp, result) + if (doLog) log?.debug("{} finishHtml {}", content.remoteAddress, result) result ?: return when (result) { null -> content.finish(404) @@ -328,7 +327,7 @@ open class RoutedHttpHandler( } fun finishText(result: Any?, content: HttpContent, doLog: Boolean = true) { - if (doLog) log?.debug("{} finishText {}", content.clientIp, result) + if (doLog) log?.debug("{} finishText {}", content.remoteAddress, result) result ?: return when (result) { null -> content.finish(404) @@ -346,7 +345,7 @@ open class RoutedHttpHandler( } fun finishJson(result: Any?, content: HttpContent, doLog: Boolean = true) { - if (doLog) log?.debug("{} finishJson {}", content.clientIp, result) + if (doLog) log?.debug("{} finishJson {}", content.remoteAddress, result) result ?: return when (result) { null -> content.finish(404) @@ -362,7 +361,7 @@ open class RoutedHttpHandler( } else -> { val json = json?.toJson(result) - if (doLog) log?.debug("{} finishJson: generate json {}", content.clientIp, json) + if (doLog) log?.debug("{} finishJson: generate json {}", content.remoteAddress, json) if (json != null) { content.finishJson(json.toByteArray()) } else { diff --git a/web/src/main/kotlin/cn/tursom/web/utils/EmptyHttpContent.kt b/web/src/main/kotlin/cn/tursom/web/utils/EmptyHttpContent.kt index a0ccb37..326f5ef 100644 --- a/web/src/main/kotlin/cn/tursom/web/utils/EmptyHttpContent.kt +++ b/web/src/main/kotlin/cn/tursom/web/utils/EmptyHttpContent.kt @@ -14,7 +14,7 @@ class EmptyHttpContent( override var responseCode: Int = 200, override var responseMessage: String? = null, override val body: ByteBuffer? = null, - override val clientIp: SocketAddress = InetSocketAddress(0), + override val remoteAddress: SocketAddress = InetSocketAddress(0), override val method: String = "GET", override val cookieMap: Map = mapOf(), override val requestSendFully: Boolean @@ -46,5 +46,6 @@ class EmptyHttpContent( override fun finishFile(file: RandomAccessFile, offset: Long, length: Long, chunkSize: Int) {} override fun addBodyParam(body: ByteBuffer) {} override fun waitBody(action: (end: Boolean) -> Unit) {} + override fun peekBody(): ByteBuffer? = null } diff --git a/web/web-coroutine/build.gradle b/web/web-coroutine/build.gradle index 6d26e67..a2ba88d 100644 --- a/web/web-coroutine/build.gradle +++ b/web/web-coroutine/build.gradle @@ -2,6 +2,6 @@ dependencies { implementation project(":web") api project(":json") api group: 'org.slf4j', name: 'slf4j-api', version: '1.7.29' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' + compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: kotlinVersion } \ No newline at end of file diff --git a/web/web-coroutine/src/main/kotlin/cn/tursom/web/Utils.kt b/web/web-coroutine/src/main/kotlin/cn/tursom/web/Utils.kt new file mode 100644 index 0000000..459838f --- /dev/null +++ b/web/web-coroutine/src/main/kotlin/cn/tursom/web/Utils.kt @@ -0,0 +1,24 @@ +package cn.tursom.web + +import cn.tursom.core.buffer.ByteBuffer +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine + +suspend fun HttpContent.getBody(): ByteBuffer { + suspendCoroutine { cont -> + waitBody { + cont.resume(it) + } + } + return body!! +} + +suspend fun HttpContent.waitBodyParam(): HttpContent { + suspendCoroutine { cont -> + waitBody { + addBodyParam() + cont.resume(it) + } + } + return this +} \ No newline at end of file diff --git a/web/web-coroutine/src/main/kotlin/cn/tursom/web/router/AsyncRoutedHttpHandler.kt b/web/web-coroutine/src/main/kotlin/cn/tursom/web/router/AsyncRoutedHttpHandler.kt index 7512d8d..70ab0ba 100644 --- a/web/web-coroutine/src/main/kotlin/cn/tursom/web/router/AsyncRoutedHttpHandler.kt +++ b/web/web-coroutine/src/main/kotlin/cn/tursom/web/router/AsyncRoutedHttpHandler.kt @@ -223,7 +223,7 @@ open class AsyncRoutedHttpHandler( fun autoReturn(method: KCallable<*>, result: Any?, content: HttpContent, doLog: Boolean? = null) { method.findAnnotation()?.let { content.setContextType(it.type.value) - log?.debug("{}: autoReturn context type auto set to {}({})", content.clientIp, it.type.key, it.type.value) + log?.debug("{}: autoReturn context type auto set to {}({})", content.remoteAddress, it.type.key, it.type.value) } autoReturn(result, content, doLog ?: method.doLog) }