增强web

This commit is contained in:
tursom 2019-12-15 01:12:02 +08:00
parent e4c6b5657e
commit 85291d9f59
10 changed files with 84 additions and 481 deletions

View File

@ -1,14 +0,0 @@
package cn.tursom.web.router.suspend
interface ISuspendRouter<T> {
suspend fun setSubRoute(route: String, value: T?, onDestroy: ((oldValue: T) -> Unit)? = null)
suspend fun delRoute(route: String, onDestroy: ((oldValue: T) -> Unit)? = null)
suspend fun set(
route: String,
onDestroy: ((oldValue: T) -> Unit)? = null,
value: T?
) = setSubRoute(route, value, onDestroy)
suspend fun get(route: String): Pair<T?, List<Pair<String, String>>>
}

View File

@ -1,145 +0,0 @@
package cn.tursom.web.router.suspend.impl
import cn.tursom.web.router.suspend.ISuspendRouter
import cn.tursom.web.router.suspend.impl.node.ISuspendColonStarNode
import cn.tursom.web.router.suspend.impl.node.SuspendAnyColonStarNode
import cn.tursom.web.router.suspend.impl.node.SuspendPlaceholderColonStarNode
import kotlinx.coroutines.runBlocking
import java.util.concurrent.Executors
@Suppress("unused", "unused", "MemberVisibilityCanBePrivate", "UNUSED_PARAMETER")
class SuspendColonStarRouter<T> : ISuspendRouter<T> {
private val rootNode = cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>(listOf(""), 0, null)
private val threadPool = Executors.newSingleThreadExecutor()
@Volatile
private var _lastChangeTime: Long = System.currentTimeMillis()
val lashChangeTime
get() = _lastChangeTime
@Volatile
private var strBuf: String = ""
@Volatile
private var strBufTime: Long = 0
val root: ISuspendColonStarNode<T> = rootNode
override suspend fun setSubRoute(
route: String,
value: T?,
onDestroy: ((oldValue: T) -> Unit)?
) {
val routeList = route.split('?')[0].split('/').filter { it.isNotEmpty() }
var routeNode = rootNode
var r: String
var index = 0
while (index < routeList.size) {
r = routeList[index]
routeNode = when {
r.isEmpty() -> routeNode
r == "*" -> routeNode.wildSubRouter ?: run {
val node = SuspendAnyColonStarNode<T>(routeList, index, null)
routeNode.wildSubRouter = node
index = routeList.size - 1
node
}
r[0] == ':' -> {
val matchLength = SuspendPlaceholderColonStarNode.matchLength(routeList, index)
val node = routeNode.getPlaceholderRouter(matchLength) ?: suspend {
routeNode.addNode(routeList, index, null)
routeNode.getPlaceholderRouter(matchLength)!!
}()
index += node.size - 1
node
}
else -> routeNode.subRouterMap[r] ?: {
val node = cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>(routeList, index, null)
routeNode.subRouterMap[r] = node
node
}()
}
index++
}
val oldValue = routeNode.value
if (oldValue != null) onDestroy?.invoke(oldValue)
routeNode.value = value
routeNode.routeList = routeList
routeNode.index = index - 1
_lastChangeTime = System.currentTimeMillis()
}
override suspend fun delRoute(route: String, onDestroy: ((oldValue: T) -> Unit)?) {
this.set(route, null, onDestroy)
}
suspend fun set(
route: String,
value: T?,
onDestroy: ((oldValue: T) -> Unit)? = null
) = setSubRoute(route, value, onDestroy)
override suspend fun get(route: String): Pair<T?, List<Pair<String, String>>> {
val list = ArrayList<Pair<String, String>>()
val endIndex = route.indexOf('?')
return rootNode.get(
(if (endIndex < 0) route else route.substring(0, endIndex))
.split('/').filter { it.isNotEmpty() },
list
)?.value to list
}
private suspend fun toString(node: cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>, stringBuilder: StringBuilder, indentation: String) {
if (
node.value == null &&
node.subRouterMap.isEmpty() &&
node.placeholderRouterListEmpty &&
node.wildSubRouter == null
) {
return
}
if (indentation.isNotEmpty()) {
stringBuilder.append(indentation)
stringBuilder.append("- ")
}
stringBuilder.append("${node.lastRoute}${if (node.value != null) " ${node.value}" else ""}\n")
if (node is SuspendAnyColonStarNode) return
val subIndentation = if (indentation.isEmpty()) "|" else "$indentation |"
node.subRouterMap.forEach { (_, u) ->
toString(u, stringBuilder, subIndentation)
}
node.forEachPlaceholderRouter {
toString(it, stringBuilder, subIndentation)
}
toString(node.wildSubRouter ?: return, stringBuilder, subIndentation)
return
}
suspend fun suspendToString(): String {
if (strBufTime < _lastChangeTime) {
val stringBuilder = StringBuilder()
toString(rootNode, stringBuilder, "")
strBuf = stringBuilder.toString()
strBufTime = System.currentTimeMillis()
}
return strBuf
}
override fun toString(): String {
if (strBufTime < _lastChangeTime) {
val stringBuilder = StringBuilder()
runBlocking {
toString(rootNode, stringBuilder, "")
}
strBuf = stringBuilder.toString()
strBufTime = System.currentTimeMillis()
}
return strBuf
}
}

View File

@ -1,10 +0,0 @@
package cn.tursom.web.router.suspend.impl.node
interface ISuspendColonStarNode<T> {
val value: T?
val lastRoute: String
val fullRoute: String
val empty: Boolean
suspend fun forEach(action: suspend (node: ISuspendColonStarNode<T>) -> Unit)
}

View File

@ -1,13 +0,0 @@
package cn.tursom.web.router.suspend.impl.node
import java.util.AbstractList
internal class SuspendAnyColonStarNode<T>(
route: List<String>,
index: Int,
value: T? = null
) : SuspendColonStarNode<T>(route, index, value) {
private val subNode = this to 1
override fun match(route: List<String>, startIndex: Int) = true to 1
override suspend fun get(route: List<String>, startIndex: Int, routeList: AbstractList<Pair<String, String>>) = subNode
}

View File

@ -1,223 +0,0 @@
package cn.tursom.web.router.suspend.impl.node
import cn.tursom.utils.asynclock.AsyncReadFirstRWLock
import cn.tursom.core.binarySearch
@Suppress("MemberVisibilityCanBePrivate")
internal open class SuspendColonStarNode<T>(
var routeList: List<String>,
var index: Int,
override var value: T? = null
) : ISuspendColonStarNode<T> {
val route: String = routeList[index]
var wildSubRouter: SuspendAnyColonStarNode<T>? = null
private val placeholderRouterListLock = AsyncReadFirstRWLock()
protected open val placeholderRouterList: ArrayList<SuspendPlaceholderColonStarNode<T>>? = ArrayList(0)
private val subRouterMapLock = AsyncReadFirstRWLock()
val subRouterMap = HashMap<String, cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>>(0)
override val lastRoute
get() = "/$route"
override val fullRoute: String by lazy {
val stringBuilder = StringBuilder("")
for (i in 0..index) {
val s = routeList[i]
if (s.isNotEmpty()) stringBuilder.append("/$s")
}
stringBuilder.toString()
}
val placeholderRouterListEmpty
get() = placeholderRouterList?.isEmpty() ?: true
override val empty: Boolean
get() = value == null &&
subRouterMap.isEmpty() &&
placeholderRouterListEmpty &&
wildSubRouter == null
override suspend fun forEach(action: suspend (node: ISuspendColonStarNode<T>) -> Unit) {
placeholderRouterListLock.doRead {
placeholderRouterList?.forEach { action(it) }
}
subRouterMapLock.doRead {
subRouterMap.forEach { (_, u) -> action(u) }
}
wildSubRouter?.let { action(it) }
}
suspend fun forEachPlaceholderRouter(block: suspend (SuspendPlaceholderColonStarNode<T>) -> Unit) {
placeholderRouterListLock.doRead { placeholderRouterList?.forEach { block(it) } }
}
suspend fun getPlaceholderRouter(length: Int): SuspendPlaceholderColonStarNode<T>? {
return placeholderRouterListLock.doRead { placeholderRouterList!!.binarySearch { it.size - length } }
}
open fun match(
route: List<String>,
startIndex: Int
): Pair<Boolean, Int> = (route.size > startIndex && route[startIndex] == this.route) to 1
suspend fun addNode(route: List<String>, startIndex: Int, value: T? = null): Int {
val r = route[startIndex]
return when {
r.isEmpty() -> return addNode(route, startIndex + 1)
r == "*" -> {
wildSubRouter = SuspendAnyColonStarNode(route, startIndex, null)
1
}
r[0] == ':' -> {
val node: SuspendPlaceholderColonStarNode<T> = SuspendPlaceholderColonStarNode(
route,
startIndex,
value = value
)
// 必须保证 placeholderRouterList 存在,而且还不能有这个长度的节点
if (placeholderRouterListLock.doRead { placeholderRouterList!!.binarySearch { it.size - node.size } } != null) {
throw Exception()
}
placeholderRouterListLock.doWrite {
placeholderRouterList?.add(node)
placeholderRouterList?.sortBy { it.size }
}
node.size
}
else -> {
subRouterMap[r] = SuspendColonStarNode(route, startIndex, value)
1
}
}
}
operator fun get(route: List<String>, startIndex: Int = 0): Pair<cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>?, Int> {
val r = route[startIndex]
if (r.isEmpty()) return this to 1
val value = subRouterMap[r]
if (value != null) return value to 1
val matchLength = route.size - startIndex
val exactRoute = placeholderRouterList?.let { list ->
list.binarySearch { matchLength - it.size }
}
if (exactRoute != null) return exactRoute to matchLength
placeholderRouterList?.let { list ->
list.forEach {
val subRoute = it.getRoute(route, startIndex + it.size)
if (subRoute != null) return subRoute to route.size - startIndex
}
}
return wildSubRouter to 1
}
fun getRoute(route: List<String>, startIndex: Int = 0): cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>? {
var index = startIndex
var routeNode = this
while (index < route.size) {
val (node, size) = routeNode[route, index]
routeNode = node ?: return null
index += size
}
return routeNode
}
open suspend fun get(
route: List<String>,
startIndex: Int = 0,
routeList: java.util.AbstractList<Pair<String, String>>
): Pair<cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>?, Int> {
val r = route[startIndex]
if (r.isEmpty()) {
return this to 1
}
val value = subRouterMapLock.doRead { subRouterMap[r] }
if (value != null) return value to 1
val matchLength = route.size - startIndex
val exactRoute = placeholderRouterListLock.doRead {
placeholderRouterList?.binarySearch { matchLength - it.size }
}
if (exactRoute != null) {
exactRoute.routeList.forEachIndexed { index, s ->
if (s.isNotEmpty() && s[0] == ':') routeList.add(s.substring(1) to route[index])
}
return exactRoute to matchLength
}
if (placeholderRouterList != null) {
val list = ArrayList<Pair<String, String>>()
val detected = placeholderRouterListLock.doRead {
placeholderRouterList?.let { routerList ->
routerList.forEach {
list.clear()
val subRoute = it.getRoute(route, startIndex + it.size, list)
if (subRoute != null) {
subRoute.routeList.forEachIndexed { index, s ->
if (s.isNotEmpty()) when {
s == "*" -> for (i in index until route.size) {
routeList.add("*" to route[i])
}
s[0] == ':' -> routeList.add(s.substring(1) to route[index])
}
}
var listIndex = 0
var routeIndex = 0
while (listIndex < list.size && routeIndex <= index) {
val s = this.routeList[routeIndex++]
if (s.isNotEmpty() && s[0] == ':') {
routeList.add(s to list[listIndex++].second)
}
}
return@doRead subRoute to route.size - startIndex
}
}
}
null
}
if (detected != null) return detected
}
for (i in startIndex until route.size)
routeList.add("*" to route[i])
return wildSubRouter to 1
}
suspend fun get(
route: List<String>,
routeList: java.util.AbstractList<Pair<String, String>>
) = getRoute(route, 0, routeList)
suspend fun getRoute(
route: List<String>,
startIndex: Int = 0,
routeList: java.util.AbstractList<Pair<String, String>>
): cn.tursom.web.router.suspend.impl.node.SuspendColonStarNode<T>? {
var index = startIndex
var routeNode = this
while (index < route.size) {
val (node, size) = routeNode.get(route, index, routeList)
routeNode = node ?: return null
index += size
}
return routeNode
}
override fun toString(): String {
val stringBuilder = StringBuilder("/")
for (i in 0..index) {
val s = routeList[i]
if (s.isNotEmpty()) stringBuilder.append("$s/")
}
if (value != null) {
stringBuilder.append(" $value")
}
return stringBuilder.toString()
}
}

View File

@ -1,53 +0,0 @@
package cn.tursom.web.router.suspend.impl.node
internal class SuspendPlaceholderColonStarNode<T>(
route: List<String>,
private val startIndex: Int = 0,
endIndex: Int = startIndex + route.matchLength(startIndex),
value: T? = null
) : SuspendColonStarNode<T>(route, endIndex - 1, value) {
override val placeholderRouterList: ArrayList<SuspendPlaceholderColonStarNode<T>>?
get() = null
val size: Int = route.matchLength(startIndex, endIndex)
override fun match(
route: List<String>,
startIndex: Int
): Pair<Boolean, Int> =
(size == route.matchLength(startIndex)) to size
override val lastRoute: String
get() {
val sb = StringBuilder()
for (i in startIndex..index) {
sb.append("/")
sb.append(routeList[i])
}
return sb.toString()
}
companion object {
@JvmStatic
private fun List<String>.matchLength(startIndex: Int, endIndex: Int = size): Int {
var length = 0
for (i in startIndex until endIndex) {
if (this[i].isEmpty()) continue
else if (this[i][0] != ':') return length
else length++
}
return length
}
@JvmStatic
fun matchLength(route: List<String>, startIndex: Int): Int {
var length = 0
for (i in startIndex until route.size) {
if (route[i].isEmpty()) continue
else if (route[i][0] != ':') return length
else length++
}
return length
}
}
}

View File

@ -0,0 +1,3 @@
package cn.tursom.web.router
annotation class BlockHandler

View File

@ -13,10 +13,16 @@ import cn.tursom.web.result.Json
import cn.tursom.web.result.Text
import cn.tursom.web.router.impl.SimpleRouter
import cn.tursom.web.utils.Chunked
import cn.tursom.web.utils.ContextType
import org.slf4j.LoggerFactory
import java.io.File
import java.io.RandomAccessFile
import java.lang.reflect.Method
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
/**
* 自动添加路径映射的处理器
@ -28,10 +34,20 @@ import java.lang.reflect.Method
@Suppress("MemberVisibilityCanBePrivate", "unused")
open class RoutedHttpHandler(
target: Any? = null,
val routerMaker: () -> Router<Pair<Any?, (HttpContent) -> Unit>> = { SimpleRouter() }
val routerMaker: () -> Router<Pair<Any?, (HttpContent) -> Any?>> = { SimpleRouter() }
) : HttpHandler<HttpContent, ExceptionContent> {
protected val router: Router<Pair<Any?, (HttpContent) -> Unit>> = routerMaker()
protected val routerMap: HashMap<String, Router<Pair<Any?, (HttpContent) -> Unit>>> = HashMap()
protected val router: Router<Pair<Any?, (HttpContent) -> Any?>> = routerMaker()
protected val routerMap: HashMap<String, Router<Pair<Any?, (HttpContent) -> Any?>>> = HashMap()
private val threadNumber = AtomicInteger(0)
val workerThread = ThreadPoolExecutor(
Runtime.getRuntime().availableProcessors() * 4,
Runtime.getRuntime().availableProcessors() * 4,
0L, TimeUnit.MILLISECONDS,
LinkedBlockingQueue<Runnable>(),
ThreadFactory {
Thread(it, "TreeDiagramWorker-${threadNumber.incrementAndGet()}")
}
)
init {
@Suppress("LeakingThis")
@ -47,7 +63,7 @@ open class RoutedHttpHandler(
}
}
open fun handle(content: HttpContent, handler: ((HttpContent) -> Unit)?) {
open fun handle(content: HttpContent, handler: ((HttpContent) -> Any?)?) {
if (handler != null) {
handler(content)
} else {
@ -73,17 +89,17 @@ open class RoutedHttpHandler(
}
}
fun addRouter(route: String, handler: (HttpContent) -> Unit) = addRouter(route, null, handler)
fun addRouter(route: String, obj: Any?, handler: (HttpContent) -> Unit) {
fun addRouter(route: String, handler: (HttpContent) -> Any?) = addRouter(route, null, handler)
fun addRouter(route: String, obj: Any?, handler: (HttpContent) -> Any?) {
router[safeRoute(route)] = obj to handler
}
fun addRouter(method: String, route: String, handler: (HttpContent) -> Unit) = addRouter(method, route, null, handler)
fun addRouter(method: String, route: String, obj: Any?, handler: (HttpContent) -> Unit) {
fun addRouter(method: String, route: String, handler: (HttpContent) -> Any?) = addRouter(method, route, null, handler)
fun addRouter(method: String, route: String, obj: Any?, handler: (HttpContent) -> Any?) {
getRouter(method)[safeRoute(route)] = obj to handler
}
fun getHandler(content: MutableHttpContent, method: String, route: String): ((HttpContent) -> Unit)? {
fun getHandler(content: MutableHttpContent, method: String, route: String): ((HttpContent) -> Any?)? {
val safeRoute = safeRoute(route)
val router = getHandler(method, safeRoute)
if (router.first != null) {
@ -94,7 +110,7 @@ open class RoutedHttpHandler(
return router.first?.second ?: this.router[safeRoute].first?.second
}
fun getHandler(method: String, route: String): Pair<Pair<Any?, (HttpContent) -> Unit>?, List<Pair<String, String>>> {
fun getHandler(method: String, route: String): Pair<Pair<Any?, (HttpContent) -> Any?>?, List<Pair<String, String>>> {
val safeRoute = safeRoute(route)
val router = getRouter(method)[safeRoute]
return if (router.first != null) router else this.router[safeRoute]
@ -115,9 +131,9 @@ open class RoutedHttpHandler(
}
}
fun addRouter(obj: Any, method: Method, route: String, router: Router<Pair<Any?, (HttpContent) -> Unit>>) {
router[safeRoute(route)] = if (method.parameterTypes.isEmpty()) {
obj to when {
fun addRouter(obj: Any, method: Method, route: String, router: Router<Pair<Any?, (HttpContent) -> Any?>>) {
router[safeRoute(route)] = obj to (if (method.parameterTypes.isEmpty()) {
when {
method.getAnnotation(Html::class.java) != null -> { content ->
method(obj)?.let { result -> finishHtml(result, content) }
}
@ -128,10 +144,10 @@ open class RoutedHttpHandler(
method(obj)?.let { result -> finishJson(result, content) }
}
else -> { content ->
method(obj)?.let { result -> autoReturn(result, content) }
method(obj)?.let { result -> autoReturn(method, result, content) }
}
}
} else obj to when (method.returnType) {
} else when (method.returnType) {
Void::class.java -> { content -> method(obj, content) }
Void.TYPE -> { content -> method(obj, content) }
Unit::class.java -> { content -> method(obj, content) }
@ -145,10 +161,15 @@ open class RoutedHttpHandler(
method.getAnnotation(Json::class.java) != null -> { content ->
method(obj, content)?.let { result -> finishJson(result, content) }
}
else -> { content ->
method(obj, content)?.let { result -> autoReturn(result, content) }
else -> { content: HttpContent ->
method(obj, content)?.let { result -> autoReturn(method, result, content) }
}
}
}).let {
if (method.getAnnotation(BlockHandler::class.java) != null) { content ->
workerThread.execute { it(content) }
} else
it
}
}
@ -185,7 +206,7 @@ open class RoutedHttpHandler(
}
}
protected fun deleteMapping(obj: Any, route: String, router: Router<Pair<Any?, (HttpContent) -> Unit>>) {
protected fun deleteMapping(obj: Any, route: String, router: Router<Pair<Any?, (HttpContent) -> Any?>>) {
val handler = router[safeRoute(route)].first
if (handler?.first == obj) {
router.delRoute(safeRoute(route))
@ -226,7 +247,7 @@ open class RoutedHttpHandler(
else -> null
}
protected fun getRouter(method: String): Router<Pair<Any?, (HttpContent) -> Unit>> = when {
protected fun getRouter(method: String): Router<Pair<Any?, (HttpContent) -> Any?>> = when {
method.isEmpty() -> router
else -> {
val upperCaseMethod = method.toUpperCase()
@ -267,6 +288,13 @@ open class RoutedHttpHandler(
if (it.endsWith('/')) it.dropLast(1) else it
}.repeatUntil({ it.contains("//") }) { it.replace(slashRegex, "/") }
fun autoReturn(method: Method, result: Any?, content: HttpContent) {
method.getAnnotation(ContextType::class.java)?.let {
content.autoContextType(it.type)
}
autoReturn(result, content)
}
fun autoReturn(result: Any?, content: HttpContent) {
log?.debug("{}: autoReturn: {}", content.clientIp, result)
result ?: return
@ -294,6 +322,12 @@ open class RoutedHttpHandler(
is ByteBuffer -> content.finishHtml(result)
is ByteArray -> content.finishHtml(result)
is String -> content.finishHtml(result.toByteArray())
is StringBuffer -> content.finishHtml(result.toString().toByteArray())
is StringBuilder -> content.finishHtml(result.toString().toByteArray())
is Chunked -> {
content.responseHtml()
content.finishChunked(result)
}
else -> content.finishHtml(result.toString().toByteArray())
}
}
@ -305,6 +339,12 @@ open class RoutedHttpHandler(
is ByteBuffer -> content.finishText(result)
is ByteArray -> content.finishText(result)
is String -> content.finishText(result.toByteArray())
is StringBuffer -> content.finishHtml(result.toString().toByteArray())
is StringBuilder -> content.finishHtml(result.toString().toByteArray())
is Chunked -> {
content.responseText()
content.finishChunked(result)
}
else -> content.finishText(result.toString().toByteArray())
}
}
@ -316,7 +356,13 @@ open class RoutedHttpHandler(
is ByteBuffer -> content.finishJson(result)
is ByteArray -> content.finishJson(result)
is String -> content.finishJson("\"$result\"".toByteArray())
is Byte, Short, Int, Long, Float, Double, Boolean -> content.finishJson(result.toString().toByteArray())
is StringBuffer -> content.finishHtml(result.toString().toByteArray())
is java.lang.StringBuilder -> content.finishHtml(result.toString().toByteArray())
is Number, Boolean -> content.finishJson(result.toString().toByteArray())
is Chunked -> {
content.responseJson()
content.finishChunked(result)
}
else -> {
val json = json?.toJson(result)
log?.debug("{}: finishJson: generate json: {}", content.clientIp, json)

View File

@ -0,0 +1,3 @@
package cn.tursom.web.utils
annotation class ContextType(val type: String)

View File

@ -7,9 +7,11 @@ import cn.tursom.web.result.Html
import cn.tursom.web.result.Json
import cn.tursom.web.result.Text
import cn.tursom.web.router.impl.SimpleRouter
import cn.tursom.web.utils.ContextType
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.slf4j.LoggerFactory
import java.lang.reflect.Method
import kotlin.reflect.KCallable
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.jvmErasure
@ -17,7 +19,7 @@ import kotlin.reflect.jvm.jvmErasure
@Suppress("ProtectedInFinal", "unused", "MemberVisibilityCanBePrivate")
open class AsyncRoutedHttpHandler(
target: Any? = null,
routerMaker: () -> Router<Pair<Any?, (HttpContent) -> Unit>> = { SimpleRouter() },
routerMaker: () -> Router<Pair<Any?, (HttpContent) -> Any?>> = { SimpleRouter() },
val asyncRouterMaker: () -> Router<Pair<Any?, suspend (HttpContent) -> Unit>> = { SimpleRouter() }
) : RoutedHttpHandler(target, routerMaker) {
protected val asyncRouter: Router<Pair<Any?, suspend (HttpContent) -> Unit>> = asyncRouterMaker()
@ -113,7 +115,7 @@ open class AsyncRoutedHttpHandler(
(method as suspend Any.() -> Any?)(obj)?.let { result -> finishJson(result, content) }
}
else -> { content ->
(method as suspend Any.() -> Any?)(obj)?.let { result -> autoReturn(result, content) }
(method as suspend Any.() -> Any?)(obj)?.let { result -> autoReturn(method, result, content) }
}
}
} else obj to when (method.returnType.jvmErasure.java) {
@ -131,7 +133,7 @@ open class AsyncRoutedHttpHandler(
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> finishJson(result, content) }
}
else -> { content ->
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> autoReturn(result, content) }
(method as suspend Any.(HttpContent) -> Any?)(obj, content)?.let { result -> autoReturn(method, result, content) }
}
}
}
@ -226,5 +228,12 @@ open class AsyncRoutedHttpHandler(
} catch (e: Throwable) {
null
}
fun autoReturn(method: KCallable<*>, result: Any?, content: HttpContent) {
method.findAnnotation<ContextType>()?.let {
content.autoContextType(it.type)
}
autoReturn(result, content)
}
}
}