com.hexagonkt.http.handlers.HttpPredicate.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of http_handlers Show documentation
Show all versions of http_handlers Show documentation
HTTP handlers used to apply many callbacks to HTTP calls.
package com.hexagonkt.http.handlers
import com.hexagonkt.handlers.Context
import com.hexagonkt.core.logging.Logger
import com.hexagonkt.http.patterns.LiteralPathPattern
import com.hexagonkt.http.model.HttpMethod
import com.hexagonkt.http.model.HttpStatus
import com.hexagonkt.http.patterns.PathPattern
import com.hexagonkt.http.patterns.createPathPattern
import com.hexagonkt.http.model.HttpCall
import kotlin.reflect.KClass
data class HttpPredicate(
val methods: Set = emptySet(),
val pathPattern: PathPattern = LiteralPathPattern(),
val exception: KClass? = null,
val status: HttpStatus? = null,
) : (Context) -> Boolean {
private companion object {
val logger: Logger = Logger(HttpPredicate::class)
}
private fun PathPattern.isEmpty(): Boolean =
pattern.isEmpty()
val predicate: (Context) -> Boolean =
if (methods.isEmpty()) log(::filterWithoutMethod)
else log(::filterWithMethod)
constructor(
methods: Set = emptySet(),
pattern: String = "",
exception: KClass? = null,
status: HttpStatus? = null,
prefix: Boolean = false,
) :
this(methods, createPathPattern(pattern, prefix), exception, status)
override fun invoke(context: Context): Boolean =
predicate(context)
fun clearMethods(): HttpPredicate =
copy(methods = emptySet())
private fun log(
predicate: (Context) -> Boolean
): (Context) -> Boolean = {
val allowed = predicate(it)
logger.debug { "${describe()} -> ${if (allowed) "ALLOWED" else "DENIED"}" }
allowed
}
private fun filterMethod(context: Context): Boolean =
context.event.request.method in methods
private fun filterPattern(context: Context): Boolean =
if (pathPattern.isEmpty() && context.event.request.path == "/") true
else pathPattern.matches(context.event.request.path)
private fun filterException(context: Context): Boolean {
val exceptionClass = context.exception?.javaClass ?: return false
return exception?.java?.isAssignableFrom(exceptionClass) ?: false
}
private fun filterStatus(context: Context): Boolean =
status == context.event.response.status
private fun filterWithoutMethod(context: Context): Boolean =
filterPattern(context)
&& (exception == null || filterException(context))
&& (status == null || filterStatus(context))
private fun filterWithMethod(context: Context): Boolean =
filterMethod(context) && filterWithoutMethod(context)
fun addPrefix(prefix: String): HttpPredicate =
copy(pathPattern = pathPattern.addPrefix(prefix))
fun describe(): String =
methods
.map { it.name }
.ifEmpty { listOf("ANY") }
.joinToString(
separator = ", ",
postfix = pathPattern.describe().prependIndent(" "),
transform = { it }
)
}