Fernando Sanchez (Perraco Labs)
10/11/2024, 9:54 AM@Serializable
public data class RouteInfo(val path: String, val method: String)
internal fun Application.collectRoutes(): List<RouteInfo> {
val routes: MutableList<RouteInfo> = mutableListOf()
// Helper function to recursively traverse and collect routes.
fun RoutingNode.collect() {
if (this.selector is HttpMethodRouteSelector) {
val method: String = (this.selector as HttpMethodRouteSelector).method.value
val path: String = this.extractRoutePath()
val routeInfo = RouteInfo(path = path, method = method)
routes.add(routeInfo)
}
this.children.forEach { it.collect() }
}
// Start collecting from the root route.
this.routing { }.children.forEach { it.collect() }
return routes.sortedWith(
compareBy(
{ it.path },
{ it.method }
)
)
}
private fun RoutingNode.extractRoutePath(): String {
val segments: MutableList<String> = mutableListOf()
var currentRoute: Route? = this
// Traverse the parent chain of the current route and collect path segments.
while (currentRoute is RoutingNode) {
val selector: RouteSelector = currentRoute.selector
when (selector) {
is PathSegmentConstantRouteSelector -> selector.value
is PathSegmentParameterRouteSelector -> "{${selector.name}}"
is PathSegmentOptionalParameterRouteSelector -> "{${selector.name}?}"
is PathSegmentWildcardRouteSelector -> "*"
is TrailingSlashRouteSelector -> "" // Ignored for path construction
is HttpMethodRouteSelector -> "" // Ignored for path construction
else -> ""
}.let { segment ->
if (segment.isNotEmpty()) {
segments.add(segment)
}
}
currentRoute = currentRoute.parent
}
return segments.asReversed().joinToString(separator = "/", prefix = "/").trimEnd('/')
}
Dominik Sandjaja
10/11/2024, 10:22 AM