Skip to content

Commit

Permalink
make param matcher slightly nicer
Browse files Browse the repository at this point in the history
  • Loading branch information
daviddenton committed Oct 15, 2020
1 parent 04d40f2 commit 8674132
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
Expand Up @@ -5,6 +5,8 @@ import org.http4k.core.HttpHandler
import org.http4k.core.Request
import org.http4k.core.Response
import org.http4k.core.then
import org.http4k.routing.RouterMatch.MatchingHandler
import org.http4k.routing.RouterMatch.Unmatched

sealed class ParameterMatch(private val predicate: (Request) -> Boolean) : (Request) -> Boolean by predicate {
infix fun bind(handler: HttpHandler): RoutingHttpHandler = PredicatedHandler(predicate, handler)
Expand All @@ -18,12 +20,20 @@ sealed class ParameterMatch(private val predicate: (Request) -> Boolean) : (Requ
}

internal class PredicatedHandler(private val predicate: (Request) -> Boolean, private val handler: HttpHandler) : RoutingHttpHandler {
override fun withFilter(new: Filter) = throw UnsupportedOperationException("Not available at the top level")
override fun withBasePath(new: String) = throw UnsupportedOperationException("Not available at the top level")
override fun match(request: Request) = if (predicate(request)) RouterMatch.MatchingHandler(handler) else RouterMatch.Unmatched
override fun withFilter(new: Filter) = PredicatedHandler(predicate, when(handler) {
is RoutingHttpHandler -> handler.withFilter(new)
else -> new.then(handler)
})

override fun withBasePath(new: String) = when(handler) {
is RoutingHttpHandler -> handler.withBasePath(new)
else -> throw UnsupportedOperationException("Cannot apply new base path without binding to an HTTP verb")
}

override fun match(request: Request) = if (predicate(request)) MatchingHandler(handler) else Unmatched

override fun invoke(request: Request): Response = when (val matchResult = match(request)) {
is RouterMatch.MatchingHandler -> matchResult(request)
is MatchingHandler -> matchResult(request)
else -> routeNotFoundHandler(request)
}
}
Expand All @@ -34,17 +44,17 @@ internal data class ParameterMatchRoutingHttpHandler(
private val notFoundHandler: HttpHandler = routeNotFoundHandler,
private val methodNotAllowedHandler: HttpHandler = routeMethodNotAllowedHandler) : RoutingHttpHandler {

override fun match(request: Request) = if (!matched(request)) RouterMatch.Unmatched else httpHandler.match(request)
override fun match(request: Request) = if (!matched(request)) Unmatched else httpHandler.match(request)

override fun invoke(request: Request): Response = when (val matchResult = match(request)) {
is RouterMatch.MatchingHandler -> matchResult(request)
is MatchingHandler -> matchResult(request)
is RouterMatch.MethodNotMatched -> methodNotAllowedHandler(request)
is RouterMatch.Unmatched -> notFoundHandler(request)
is Unmatched -> notFoundHandler(request)
}

override fun withFilter(new: Filter): RoutingHttpHandler = ParameterMatchRoutingHttpHandler(
matched,
new.then(httpHandler),
httpHandler.withFilter(new),
new.then(notFoundHandler),
new.then(methodNotAllowedHandler)
)
Expand Down
Expand Up @@ -30,7 +30,10 @@ internal data class TemplateRoutingHttpHandler(
}

override fun withFilter(new: Filter): RoutingHttpHandler =
copy(httpHandler = new.then(httpHandler), notFoundHandler = new.then(notFoundHandler), methodNotAllowedHandler = new.then(methodNotAllowedHandler))
copy(httpHandler = new.then(httpHandler),
notFoundHandler = new.then(notFoundHandler),
methodNotAllowedHandler = new.then(methodNotAllowedHandler)
)

override fun withBasePath(new: String): RoutingHttpHandler = copy(template = UriTemplate.from("$new/$template"))
}
Expand Up @@ -3,6 +3,7 @@ package org.http4k.routing
import com.natpryce.hamkrest.and
import com.natpryce.hamkrest.assertion.assertThat
import com.natpryce.hamkrest.present
import com.natpryce.hamkrest.throws
import org.http4k.core.Method.GET
import org.http4k.core.Request
import org.http4k.core.Response
Expand Down Expand Up @@ -31,6 +32,11 @@ class ParameterMatchRoutingHttpHandlerTest : RoutingHttpHandlerContract() {
assertThat(withBasePath.matchAndInvoke(prefixReq), criteria)
assertThat(withBasePath(prefixReq), criteria)
}

@Test
fun `attempt to bind param handler without a verb`() {
assertThat({ routes(prefix bind (headers("host") bind { Response(OK) })) }, throws<UnsupportedOperationException>())
}
}

class ParameterMatchRoutingHttpHandlerAlternateTest : RoutingHttpHandlerContract() {
Expand Down

0 comments on commit 8674132

Please sign in to comment.