PathHandler.kt
package com.hexagonkt.http.handlers
import com.hexagonkt.core.logging.Logger
import com.hexagonkt.core.media.TEXT_PLAIN
import com.hexagonkt.core.toText
import com.hexagonkt.handlers.ChainHandler
import com.hexagonkt.handlers.Handler
import com.hexagonkt.http.model.*
import com.hexagonkt.http.model.HttpMethod.Companion.ALL
import com.hexagonkt.http.model.HttpStatusType.SERVER_ERROR
data class PathHandler(
override val handlerPredicate: HttpPredicate,
val handlers: List<HttpHandler>
) :
HttpHandler,
Handler<HttpCall> by ChainHandler(
handlers.map { it.addPrefix(handlerPredicate.pathPattern.pattern) },
handlerPredicate
)
{
private companion object {
val logger: Logger = Logger(PathHandler::class)
fun nestedMethods(handlers: List<HttpHandler>): Set<HttpMethod> =
handlers
.flatMap { it.handlerPredicate.methods.ifEmpty { ALL } }
.toSet()
}
constructor(vararg handlers: HttpHandler) :
this(
HttpPredicate(methods = nestedMethods(handlers.toList())),
handlers.toList()
)
constructor(pattern: String, handlers: List<HttpHandler>) :
this(
HttpPredicate(
methods = nestedMethods(handlers.toList()),
pattern = pattern,
prefix = true,
),
handlers
)
constructor(pattern: String, vararg handlers: HttpHandler) :
this(pattern, handlers.toList())
override fun process(request: HttpRequestPort): HttpContext =
process(HttpContext(HttpCall(request = request), predicate)).let {
val event = it.event
val response = event.response
val exception = it.exception
if (exception != null) {
logger.error(exception) {
"Exception received at call processing end. Clear/handle exception in a handler"
}
if (response.status.type != SERVER_ERROR)
it.with(
event = event.copy(
response = response.with(
body = exception.toText(),
contentType = ContentType(TEXT_PLAIN),
status = INTERNAL_SERVER_ERROR_500,
)
)
)
else
it
}
else {
it
}
} as HttpContext
override fun addPrefix(prefix: String): HttpHandler =
copy(handlerPredicate = handlerPredicate.addPrefix(prefix))
fun describe(): String =
listOf(
listOf(handlerPredicate.describe()),
handlers
.map {
when (it) {
is PathHandler -> it.describe()
else -> it.handlerPredicate.describe()
}
}
.map {it.prependIndent(" ".repeat(4)) }
)
.flatten()
.joinToString("\n") { it }
}