From a0ab043e5acb2bef8ae4fd333273102b5c31ce2c Mon Sep 17 00:00:00 2001 From: Ryan Brink <5607577+rgbrizzlehizzle@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:17:05 -0400 Subject: [PATCH] added explicit path calculator interface (#31) --- CHANGELOG.md | 10 ++++ gradle.properties | 2 +- .../org/leafygreens/kompendium/Kompendium.kt | 13 +++-- .../kompendium/path/CorePathCalculator.kt | 48 +++++++++++++++++++ .../kompendium/path/PathCalculator.kt | 11 +++++ .../leafygreens/kompendium/util/Helpers.kt | 41 ---------------- 6 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/CorePathCalculator.kt create mode 100644 kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/PathCalculator.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dd0daa9e..e1d6ddca1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## [0.5.2] - April 19th, 2021 + +### Removed + +- Removed `Route.calculatePath` + +### Added + +- Added an explicit `PathCalculator` interface to allow for easier handling of routes external to the core set of Ktor route selectors. + ## [0.5.1] - April 19th, 2021 ### Changed diff --git a/gradle.properties b/gradle.properties index 00f262e4e..886b0251c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ # Kompendium -project.version=0.5.1 +project.version=0.5.2 # Kotlin kotlin.code.style=official # Gradle diff --git a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/Kompendium.kt b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/Kompendium.kt index d3c4f1a8b..fc6fdf68c 100644 --- a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/Kompendium.kt +++ b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/Kompendium.kt @@ -31,7 +31,8 @@ import org.leafygreens.kompendium.models.oas.OpenApiSpecReferenceObject import org.leafygreens.kompendium.models.oas.OpenApiSpecRequest import org.leafygreens.kompendium.models.oas.OpenApiSpecResponse import org.leafygreens.kompendium.models.oas.OpenApiSpecSchemaRef -import org.leafygreens.kompendium.util.Helpers.calculatePath +import org.leafygreens.kompendium.path.CorePathCalculator +import org.leafygreens.kompendium.path.PathCalculator import org.leafygreens.kompendium.util.Helpers.getReferenceSlug object Kompendium { @@ -44,12 +45,14 @@ object Kompendium { paths = mutableMapOf() ) + var pathCalculator: PathCalculator = CorePathCalculator() + @OptIn(ExperimentalStdlibApi::class) inline fun Route.notarizedGet( info: MethodInfo, noinline body: PipelineInterceptor ): Route = notarizationPreFlight() { paramType, requestType, responseType -> - val path = calculatePath() + val path = pathCalculator.calculate(this) openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() } openApiSpec.paths[path]?.get = info.parseMethodInfo(HttpMethod.Get, paramType, requestType, responseType) return method(HttpMethod.Get) { handle(body) } @@ -59,7 +62,7 @@ object Kompendium { info: MethodInfo, noinline body: PipelineInterceptor ): Route = notarizationPreFlight() { paramType, requestType, responseType -> - val path = calculatePath() + val path = pathCalculator.calculate(this) openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() } openApiSpec.paths[path]?.post = info.parseMethodInfo(HttpMethod.Post, paramType, requestType, responseType) return method(HttpMethod.Post) { handle(body) } @@ -69,7 +72,7 @@ object Kompendium { info: MethodInfo, noinline body: PipelineInterceptor, ): Route = notarizationPreFlight() { paramType, requestType, responseType -> - val path = calculatePath() + val path = pathCalculator.calculate(this) openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() } openApiSpec.paths[path]?.put = info.parseMethodInfo(HttpMethod.Put, paramType, requestType, responseType) return method(HttpMethod.Put) { handle(body) } @@ -79,7 +82,7 @@ object Kompendium { info: MethodInfo, noinline body: PipelineInterceptor ): Route = notarizationPreFlight { paramType, requestType, responseType -> - val path = calculatePath() + val path = pathCalculator.calculate(this) openApiSpec.paths.getOrPut(path) { OpenApiSpecPathItem() } openApiSpec.paths[path]?.delete = info.parseMethodInfo(HttpMethod.Delete, paramType, requestType, responseType) return method(HttpMethod.Delete) { handle(body) } diff --git a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/CorePathCalculator.kt b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/CorePathCalculator.kt new file mode 100644 index 000000000..6fb65a599 --- /dev/null +++ b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/CorePathCalculator.kt @@ -0,0 +1,48 @@ +package org.leafygreens.kompendium.path + +import io.ktor.routing.PathSegmentConstantRouteSelector +import io.ktor.routing.PathSegmentParameterRouteSelector +import io.ktor.routing.RootRouteSelector +import io.ktor.routing.Route +import io.ktor.util.InternalAPI +import org.slf4j.LoggerFactory + +open class CorePathCalculator : PathCalculator { + + private val logger = LoggerFactory.getLogger(javaClass) + + @OptIn(InternalAPI::class) + override fun calculate( + route: Route?, + tail: String + ): String = when (route) { + null -> tail + else -> when (route.selector) { + is RootRouteSelector -> { + logger.debug("Root route detected, returning path: $tail") + tail + } + is PathSegmentParameterRouteSelector -> { + logger.debug("Found segment parameter ${route.selector}, continuing to parent") + val newTail = "/${route.selector}$tail" + calculate(route.parent, newTail) + } + is PathSegmentConstantRouteSelector -> { + logger.debug("Found segment constant ${route.selector}, continuing to parent") + val newTail = "/${route.selector}$tail" + calculate(route.parent, newTail) + } + else -> when (route.selector.javaClass.simpleName) { + "TrailingSlashRouteSelector" -> { + logger.debug("Found trailing slash route selector") + val newTail = tail.ifBlank { "/" } + calculate(route.parent, newTail) + } + else -> handleCustomSelectors(route, tail) + } + } + } + + override fun handleCustomSelectors(route: Route, tail: String): String = error("Unknown selector ${route.selector}") + +} diff --git a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/PathCalculator.kt b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/PathCalculator.kt new file mode 100644 index 000000000..89f6752a3 --- /dev/null +++ b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/path/PathCalculator.kt @@ -0,0 +1,11 @@ +package org.leafygreens.kompendium.path + +import io.ktor.routing.Route + +interface PathCalculator { + + fun calculate(route: Route?, tail: String = ""): String + + fun handleCustomSelectors(route: Route, tail: String): String + +} diff --git a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt index 2d12a1732..1fe4ed643 100644 --- a/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt +++ b/kompendium-core/src/main/kotlin/org/leafygreens/kompendium/util/Helpers.kt @@ -18,47 +18,6 @@ object Helpers { const val COMPONENT_SLUG = "#/components/schemas" - /** - * TODO Explain this - */ - @OptIn(InternalAPI::class) - fun Route.calculatePath(tail: String = ""): String { - logger.info("Building path for ${selector::class}") - return when (selector) { - is RootRouteSelector -> { - logger.info("Root route detected, returning path: $tail") - tail - } - is PathSegmentParameterRouteSelector -> { - logger.info("Found segment parameter $selector, continuing to parent") - val newTail = "/$selector$tail" - parent?.calculatePath(newTail) ?: run { - logger.info("No parent found, returning current path") - newTail - } - } - is PathSegmentConstantRouteSelector -> { - logger.info("Found segment constant $selector, continuing to parent") - val newTail = "/$selector$tail" - parent?.calculatePath(newTail) ?: run { - logger.info("No parent found, returning current path") - newTail - } - } - else -> when (selector.javaClass.simpleName) { - // dumb ass workaround to this object being internal to ktor - "TrailingSlashRouteSelector" -> { - logger.info("Found trailing slash route selector") - val newTail = tail.ifBlank { "/" } - parent?.calculatePath(newTail) ?: run { - logger.info("No parent found, returning current path") - newTail - } - } - else -> error("Unhandled selector type ${selector::class}") - } - } - } /** * Simple extension function that will take a [Pair] and place it (if absent) into a [MutableMap].