mirror of
https://github.com/tursom/TursomServer.git
synced 2025-02-08 18:50:11 +08:00
Http功能增强
This commit is contained in:
parent
cb61ac0ca7
commit
367b3067c0
@ -20,181 +20,181 @@ import kotlin.collections.set
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate", "unused")
|
||||
open class NettyHttpContent(
|
||||
val ctx: ChannelHandlerContext,
|
||||
val msg: FullHttpRequest
|
||||
val ctx: ChannelHandlerContext,
|
||||
val msg: FullHttpRequest
|
||||
) : AdvanceHttpContent {
|
||||
override val uri: String by lazy {
|
||||
var uri = msg.uri()
|
||||
while (uri.contains("//")) {
|
||||
uri = uri.replace("//", "/")
|
||||
}
|
||||
uri
|
||||
override val uri: String by lazy {
|
||||
var uri = msg.uri()
|
||||
while (uri.contains("//")) {
|
||||
uri = uri.replace("//", "/")
|
||||
}
|
||||
override val clientIp get() = ctx.channel().remoteAddress()!!
|
||||
override val realIp: String = super.realIp
|
||||
val httpMethod: HttpMethod get() = msg.method()
|
||||
val protocolVersion: HttpVersion get() = msg.protocolVersion()
|
||||
val headers: HttpHeaders get() = msg.headers()
|
||||
protected val paramMap by lazy { RequestParser.parse(msg) }
|
||||
override val cookieMap by lazy { getHeader("Cookie")?.let { decodeCookie(it) } ?: mapOf() }
|
||||
override val body = msg.content()?.let { NettyByteBuffer(it) }
|
||||
uri
|
||||
}
|
||||
override val clientIp get() = ctx.channel().remoteAddress()!!
|
||||
override val realIp: String = super.realIp
|
||||
val httpMethod: HttpMethod get() = msg.method()
|
||||
val protocolVersion: HttpVersion get() = msg.protocolVersion()
|
||||
val headers: HttpHeaders get() = msg.headers()
|
||||
protected val paramMap by lazy { RequestParser.parse(msg) }
|
||||
override val cookieMap by lazy { getHeader("Cookie")?.let { decodeCookie(it) } ?: mapOf() }
|
||||
override val body = msg.content()?.let { NettyByteBuffer(it) }
|
||||
|
||||
val responseMap = HashMap<String, Any>()
|
||||
val responseListMap = HashMap<String, ArrayList<Any>>()
|
||||
override val responseBody = ByteArrayOutputStream()
|
||||
override var responseCode: Int = 200
|
||||
override var responseMessage: String? = null
|
||||
override val method: String get() = httpMethod.name()
|
||||
val chunkedList = ArrayList<ByteBuffer>()
|
||||
val responseMap = HashMap<String, Any>()
|
||||
val responseListMap = HashMap<String, ArrayList<Any>>()
|
||||
override val responseBody = ByteArrayOutputStream()
|
||||
override var responseCode: Int = 200
|
||||
override var responseMessage: String? = null
|
||||
override val method: String get() = httpMethod.name()
|
||||
val chunkedList = ArrayList<ByteBuffer>()
|
||||
|
||||
override fun getHeader(header: String): String? {
|
||||
return headers[header]
|
||||
override fun getHeader(header: String): String? {
|
||||
return headers[header]
|
||||
}
|
||||
|
||||
override fun getHeaders(): List<Map.Entry<String, String>> {
|
||||
return headers.toList()
|
||||
}
|
||||
|
||||
override fun getParam(param: String): String? {
|
||||
return paramMap[param]?.get(0)
|
||||
}
|
||||
|
||||
override fun getParams(): Map<String, List<String>> {
|
||||
return paramMap
|
||||
}
|
||||
|
||||
override fun getParams(param: String): List<String>? {
|
||||
return paramMap[param]
|
||||
}
|
||||
|
||||
override fun addParam(key: String, value: String) {
|
||||
if (!paramMap.containsKey(key)) {
|
||||
paramMap[key] = ArrayList()
|
||||
}
|
||||
(paramMap[key] as ArrayList).add(value)
|
||||
}
|
||||
|
||||
override fun setResponseHeader(name: String, value: Any) {
|
||||
responseMap[name] = value
|
||||
}
|
||||
|
||||
override fun addResponseHeader(name: String, value: Any) {
|
||||
val list = responseListMap[name] ?: run {
|
||||
val newList = ArrayList<Any>()
|
||||
responseListMap[name] = newList
|
||||
newList
|
||||
}
|
||||
list.add(value)
|
||||
}
|
||||
|
||||
override fun write(message: String) {
|
||||
responseBody.write(message.toByteArray())
|
||||
}
|
||||
|
||||
override fun write(byte: Byte) {
|
||||
responseBody.write(byte.toInt())
|
||||
}
|
||||
|
||||
override fun write(bytes: ByteArray, offset: Int, size: Int) {
|
||||
responseBody.write(bytes, offset, size)
|
||||
}
|
||||
|
||||
override fun write(buffer: ByteBuffer) {
|
||||
buffer.writeTo(responseBody)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
responseBody.reset()
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
finish(responseBody.buf, 0, responseBody.size())
|
||||
}
|
||||
|
||||
override fun finish(buffer: ByteArray, offset: Int, size: Int) {
|
||||
finish(Unpooled.wrappedBuffer(buffer, offset, size))
|
||||
}
|
||||
|
||||
override fun finish(buffer: ByteBuffer) {
|
||||
if (buffer is NettyByteBuffer) {
|
||||
finish(buffer.byteBuf)
|
||||
} else {
|
||||
super.finish(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
fun finish(buf: ByteBuf) = finish(buf, HttpResponseStatus.valueOf(responseCode))
|
||||
fun finish(buf: ByteBuf, responseCode: HttpResponseStatus) {
|
||||
val response = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseCode, buf)
|
||||
finish(response)
|
||||
}
|
||||
|
||||
fun finish(response: FullHttpResponse) {
|
||||
val heads = response.headers()
|
||||
addHeaders(
|
||||
heads, mapOf(
|
||||
HttpHeaderNames.CONTENT_TYPE to "${HttpHeaderValues.TEXT_PLAIN}; charset=UTF-8",
|
||||
HttpHeaderNames.CONTENT_LENGTH to response.content().readableBytes(),
|
||||
HttpHeaderNames.CONNECTION to HttpHeaderValues.KEEP_ALIVE
|
||||
)
|
||||
)
|
||||
|
||||
ctx.writeAndFlush(response)
|
||||
}
|
||||
|
||||
fun addHeaders(heads: HttpHeaders, defaultHeaders: Map<out CharSequence, Any>) {
|
||||
responseListMap.forEach { (t, u) ->
|
||||
u.forEach {
|
||||
heads.add(t, it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getHeaders(): List<Map.Entry<String, String>> {
|
||||
return headers.toList()
|
||||
defaultHeaders.forEach { (t, u) ->
|
||||
heads.set(t, u)
|
||||
}
|
||||
|
||||
override fun getParam(param: String): String? {
|
||||
return paramMap[param]?.get(0)
|
||||
responseMap.forEach { (t, u) ->
|
||||
heads.set(t, u)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getParams(): Map<String, List<String>> {
|
||||
return paramMap
|
||||
}
|
||||
override fun writeChunkedHeader() {
|
||||
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)
|
||||
response.status = if (responseMessage != null) HttpResponseStatus(responseCode, responseMessage)
|
||||
else HttpResponseStatus.valueOf(responseCode)
|
||||
val heads = response.headers()
|
||||
addHeaders(
|
||||
heads, mapOf(
|
||||
HttpHeaderNames.CONTENT_TYPE to "${HttpHeaderValues.TEXT_PLAIN}; charset=UTF-8",
|
||||
HttpHeaderNames.CONNECTION to HttpHeaderValues.KEEP_ALIVE,
|
||||
HttpHeaderNames.TRANSFER_ENCODING to "chunked"
|
||||
)
|
||||
)
|
||||
ctx.write(response)
|
||||
}
|
||||
|
||||
override fun getParams(param: String): List<String>? {
|
||||
return paramMap[param]
|
||||
}
|
||||
override fun addChunked(buffer: ByteBuffer) {
|
||||
chunkedList.add(buffer)
|
||||
}
|
||||
|
||||
override fun addParam(key: String, value: String) {
|
||||
if (!paramMap.containsKey(key)) {
|
||||
paramMap[key] = ArrayList()
|
||||
}
|
||||
(paramMap[key] as ArrayList).add(value)
|
||||
}
|
||||
override fun finishChunked() {
|
||||
val httpChunkWriter = HttpChunkedInput(NettyChunkedByteBuffer(chunkedList))
|
||||
ctx.writeAndFlush(httpChunkWriter)
|
||||
}
|
||||
|
||||
override fun setResponseHeader(name: String, value: Any) {
|
||||
responseMap[name] = value
|
||||
}
|
||||
override fun finishChunked(chunked: Chunked) {
|
||||
val httpChunkWriter = HttpChunkedInput(NettyChunkedInput(chunked))
|
||||
ctx.writeAndFlush(httpChunkWriter)
|
||||
}
|
||||
|
||||
override fun addResponseHeader(name: String, value: Any) {
|
||||
val list = responseListMap[name] ?: run {
|
||||
val newList = ArrayList<Any>()
|
||||
responseListMap[name] = newList
|
||||
newList
|
||||
}
|
||||
list.add(value)
|
||||
}
|
||||
override fun finishFile(file: File, chunkSize: Int) {
|
||||
writeChunkedHeader()
|
||||
ctx.writeAndFlush(HttpChunkedInput(ChunkedFile(file, chunkSize)))
|
||||
}
|
||||
|
||||
override fun write(message: String) {
|
||||
responseBody.write(message.toByteArray())
|
||||
}
|
||||
|
||||
override fun write(byte: Byte) {
|
||||
responseBody.write(byte.toInt())
|
||||
}
|
||||
|
||||
override fun write(bytes: ByteArray, offset: Int, size: Int) {
|
||||
responseBody.write(bytes, offset, size)
|
||||
}
|
||||
|
||||
override fun write(buffer: ByteBuffer) {
|
||||
buffer.writeTo(responseBody)
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
responseBody.reset()
|
||||
}
|
||||
|
||||
override fun finish() {
|
||||
finish(responseBody.buf, 0, responseBody.size())
|
||||
}
|
||||
|
||||
override fun finish(buffer: ByteArray, offset: Int, size: Int) {
|
||||
finish(Unpooled.wrappedBuffer(buffer, offset, size))
|
||||
}
|
||||
|
||||
override fun finish(buffer: ByteBuffer) {
|
||||
if (buffer is NettyByteBuffer) {
|
||||
finish(buffer.byteBuf)
|
||||
} else {
|
||||
super.finish(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
fun finish(buf: ByteBuf) = finish(buf, HttpResponseStatus.valueOf(responseCode))
|
||||
fun finish(buf: ByteBuf, responseCode: HttpResponseStatus) {
|
||||
val response = DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseCode, buf)
|
||||
finish(response)
|
||||
}
|
||||
|
||||
fun finish(response: FullHttpResponse) {
|
||||
val heads = response.headers()
|
||||
addHeaders(
|
||||
heads, mapOf(
|
||||
HttpHeaderNames.CONTENT_TYPE to "${HttpHeaderValues.TEXT_PLAIN}; charset=UTF-8",
|
||||
HttpHeaderNames.CONTENT_LENGTH to response.content().readableBytes(),
|
||||
HttpHeaderNames.CONNECTION to HttpHeaderValues.KEEP_ALIVE
|
||||
)
|
||||
)
|
||||
|
||||
ctx.writeAndFlush(response)
|
||||
}
|
||||
|
||||
fun addHeaders(heads: HttpHeaders, defaultHeaders: Map<out CharSequence, Any>) {
|
||||
responseListMap.forEach { (t, u) ->
|
||||
u.forEach {
|
||||
heads.add(t, it)
|
||||
}
|
||||
}
|
||||
|
||||
defaultHeaders.forEach { (t, u) ->
|
||||
heads.set(t, u)
|
||||
}
|
||||
|
||||
responseMap.forEach { (t, u) ->
|
||||
heads.set(t, u)
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeChunkedHeader() {
|
||||
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)
|
||||
response.status = if (responseMessage != null) HttpResponseStatus(responseCode, responseMessage)
|
||||
else HttpResponseStatus.valueOf(responseCode)
|
||||
val heads = response.headers()
|
||||
addHeaders(
|
||||
heads, mapOf(
|
||||
HttpHeaderNames.CONTENT_TYPE to "${HttpHeaderValues.TEXT_PLAIN}; charset=UTF-8",
|
||||
HttpHeaderNames.CONNECTION to HttpHeaderValues.KEEP_ALIVE,
|
||||
HttpHeaderNames.TRANSFER_ENCODING to "chunked"
|
||||
)
|
||||
)
|
||||
ctx.write(response)
|
||||
}
|
||||
|
||||
override fun addChunked(buffer: ByteBuffer) {
|
||||
chunkedList.add(buffer)
|
||||
}
|
||||
|
||||
override fun finishChunked() {
|
||||
val httpChunkWriter = HttpChunkedInput(NettyChunkedByteBuffer(chunkedList))
|
||||
ctx.writeAndFlush(httpChunkWriter)
|
||||
}
|
||||
|
||||
override fun finishChunked(chunked: Chunked) {
|
||||
val httpChunkWriter = HttpChunkedInput(NettyChunkedInput(chunked))
|
||||
ctx.writeAndFlush(httpChunkWriter)
|
||||
}
|
||||
|
||||
override fun finishFile(file: File, chunkSize: Int) {
|
||||
writeChunkedHeader()
|
||||
ctx.writeAndFlush(HttpChunkedInput(ChunkedFile(file, chunkSize)))
|
||||
}
|
||||
|
||||
override fun finishFile(file: RandomAccessFile, offset: Long, length: Long, chunkSize: Int) {
|
||||
writeChunkedHeader()
|
||||
ctx.writeAndFlush(HttpChunkedInput(ChunkedFile(file, offset, length, chunkSize)))
|
||||
}
|
||||
override fun finishFile(file: RandomAccessFile, offset: Long, length: Long, chunkSize: Int) {
|
||||
writeChunkedHeader()
|
||||
ctx.writeAndFlush(HttpChunkedInput(ChunkedFile(file, offset, length, chunkSize)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,4 +174,26 @@ interface HttpContent {
|
||||
)
|
||||
|
||||
fun setContextType(type: Any) = setResponseHeader("Content-Type", type)
|
||||
|
||||
fun jump(url: String) = temporaryMoved(url)
|
||||
fun moved(url: String) = permanentlyMoved(url)
|
||||
|
||||
fun permanentlyMoved(url: String) {
|
||||
setResponseHeader("Location", url)
|
||||
finish(301)
|
||||
}
|
||||
|
||||
fun temporaryMoved(url: String) {
|
||||
noStore()
|
||||
setResponseHeader("Location", url)
|
||||
finish(302)
|
||||
}
|
||||
|
||||
fun noCache() {
|
||||
setResponseHeader("Cache-Control", "no-cache")
|
||||
}
|
||||
|
||||
fun noStore() {
|
||||
setResponseHeader("Cache-Control", "no-store")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user