Skip to content

Commit

Permalink
Resolve to parent route if it has a handler and child quality is "mis…
Browse files Browse the repository at this point in the history
…sing". Fix #53
  • Loading branch information
orangy committed Dec 6, 2016
1 parent 9e8410d commit 76ee1ee
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class RoutingResolveTest {

@Test fun `routing foo with optional parameter`() {
val root = routing()
val paramEntry = root.selectHandle(UriPartConstantRouteSelector("foo"))
val paramEntry = root.select(UriPartConstantRouteSelector("foo"))
.selectHandle(UriPartOptionalParameterRouteSelector("param"))

on("resolving /foo/value") {
Expand Down Expand Up @@ -241,7 +241,7 @@ class RoutingResolveTest {

@Test fun `routing foo with anonymous tailcard`() {
val root = routing()
val paramEntry = root.selectHandle(UriPartConstantRouteSelector("foo"))
val paramEntry = root.select(UriPartConstantRouteSelector("foo"))
.selectHandle(UriPartTailcardRouteSelector())

on("resolving /foo/value") {
Expand Down Expand Up @@ -280,7 +280,7 @@ class RoutingResolveTest {

@Test fun `routing foo with named tailcard`() {
val root = routing()
val paramEntry = root.selectHandle(UriPartConstantRouteSelector("foo"))
val paramEntry = root.select(UriPartConstantRouteSelector("foo"))
.selectHandle(UriPartTailcardRouteSelector("items"))

on("resolving /foo/value") {
Expand Down Expand Up @@ -376,7 +376,7 @@ class RoutingResolveTest {

@Test fun `routing foo with quality`() {
val root = routing()
val fooEntry = root.selectHandle(UriPartConstantRouteSelector("foo"))
val fooEntry = root.select(UriPartConstantRouteSelector("foo"))
val paramEntry = fooEntry.selectHandle(UriPartParameterRouteSelector("name"))
val constantEntry = fooEntry.selectHandle(UriPartConstantRouteSelector("admin"))

Expand Down Expand Up @@ -460,4 +460,32 @@ class RoutingResolveTest {
}
}
}

@Test fun `select most specific route with root`() {
val routing = routing()
val rootEntry = routing.createRoute("/").apply { handle {} }
val varargEntry = routing.createRoute("/{...}").apply { handle {} }

on("resolving /") {
val resolveResult = context(routing, "/").resolve()

it("should successfully resolve") {
assertTrue(resolveResult.succeeded)
}
it("should resolve to rootEntry") {
assertEquals(rootEntry, resolveResult.entry)
}
}
on("resolving /path") {
val resolveResult = context(routing, "/path").resolve()

it("should successfully resolve") {
assertTrue(resolveResult.succeeded)
}
it("should resolve to varargEntry") {
assertEquals(varargEntry, resolveResult.entry)
}
}

}
}
12 changes: 5 additions & 7 deletions ktor-core/src/org/jetbrains/ktor/routing/RouteSelector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ data class RouteSelectorEvaluation(val succeeded: Boolean,

val qualityConstant = 1.0
val qualityParameter = 0.8
val qualityMissing = 0.5
val qualityWildcard = 0.2
val qualityWildcard = 0.5
val qualityMissing = 0.2
}
}

Expand Down Expand Up @@ -136,11 +136,9 @@ object UriPartWildcardRouteSelector : RouteSelector {

data class UriPartTailcardRouteSelector(val name: String = "") : RouteSelector {
override fun evaluate(context: RoutingResolveContext, index: Int): RouteSelectorEvaluation {
if (index <= context.path.size) {
val values = if (name.isEmpty()) valuesOf() else valuesOf(name to context.path.drop(index).map { it })
return RouteSelectorEvaluation(true, RouteSelectorEvaluation.qualityWildcard, values, segmentIncrement = context.path.size - index)
}
return RouteSelectorEvaluation.Failed
val values = if (name.isEmpty()) valuesOf() else valuesOf(name to context.path.drop(index).map { it })
val quality = if (index < context.path.size) RouteSelectorEvaluation.qualityWildcard else RouteSelectorEvaluation.qualityMissing
return RouteSelectorEvaluation(true, quality, values, segmentIncrement = context.path.size - index)
}

override fun toString(): String = "{...}"
Expand Down
13 changes: 7 additions & 6 deletions ktor-core/src/org/jetbrains/ktor/routing/RoutingResolve.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ class RoutingResolveContext(val routing: Route,
bestResult = RoutingResolveResult(true, subtreeResult.entry, combinedValues, combinedQuality)
}

if (bestResult != null)
return bestResult

// no child matched, match is either current entry if path is done & there is a handler, or failure
if (segmentIndex == request.path.size && entry.handlers.isNotEmpty())
if (segmentIndex == request.path.size && entry.handlers.isNotEmpty()) {
if (bestResult != null && bestResult.quality > RouteSelectorEvaluation.qualityMissing)
return bestResult

return RoutingResolveResult(true, entry, ValuesMap.Empty, 1.0)
else
return RoutingResolveResult(false, failEntry ?: entry, ValuesMap.Empty, 0.0)
}

return bestResult ?: RoutingResolveResult(false, failEntry ?: entry, ValuesMap.Empty, 0.0)
}
}

Expand Down

0 comments on commit 76ee1ee

Please sign in to comment.