Kotlin Routing
A multiplatform, extensible and independent “navigation” routing library powered by Ktor. Create routing independent and extend to what you need.
val router = routing { route(path = "/login") { // handle {} is generic for any routing event (pop, push, replace, replaceAll...) handle { val application = call.application val routeMethod = call.routeMethod (RouteMethod.Pop, RouteMethod.Push, RouteMethod.Replace, RouteMethod.ReplaceAll) val uri = call.uri val attributes = call.attributes // Always empty by default val parameters = call.parameters // All in one (path parameters ({...}) + routing parameters (push(parameters = ...)) + query parameters ("/path?q=search&name=routing")) // Here is your time // Are you on Android? Do your Intent or finish your Activity // Are you on Desktop? Use your Stack based navigation and navigate // Are you on iOS? Do your navigation like using UINavigationController // Are you on Web? Push, replace or pop your history state } } } // And to route do: router.push(path = "/login")
Declaring routes
Based on Ktor Routing
val router = routing { // name is optional and used to named navigation route(path = "/path", name = "path") { handle { // handle any routing action to this route (pop, push, replace, ...) } } // name is optional and used to named navigation route(path = "/path2", name = "path2") { push { // handle push to this route only } replace { // handle replace to this route only } replaceAll { // handle replaceAll to this route only } pop { // handle pop to this route only } } // handle is short version to combine route { handle{} } handle(path = "/path3", name = "path3") { // handle any routing action to this route (pop, push, replace, ...) } // push is short version to combine route { push{} } push(path = "/path4", name = "path4") { // handle push to this route only } // push is short version to combine route { replace{} } replace(path = "/path5", name = "path5") { // handle replace to this route only } // push is short version to combine route { replaceAll{} } replaceAll(path = "/path6", name = "path6") { // handle replaceAll to this route only } // pop is short version to combine route { pop{} } // pop can not be named pop(path = "/path7") { // handle pop to this route only } // If you need redirect one route to another do: route|handle|push|replace|replaceAll|pop(...) { redirectToPath(path = "/path-destination") // or redirectToName(name = "destination-name") } // If you need a route Regex based do: route|handle|push|replace|replaceAll|pop(path = Regex()) { // ... } }
Routing routes
There is no behavior in Ktor for that
val router = routing { // ... } // Pushing a path router.push(path = "/path") // Pushing a path with parameters router.push(path = "/path", parameters = parametersOf("number", "123")) // Pushing a name router.pushNamed(name = "name") // Pushing a name with parameters router.pushNamed(name = "name", parameters = parametersOf("number", "123")) // Pushing a name with parameters and path parameters ("/path/{id}") router.pushNamed( name = "name", pathParameters = parametersOf("id", "456"), // It will be used to do a replace in the path parameters = parametersOf("number", "123"), ) // Replacing or replacing all works the same as push but 'replace' instead push :D router.replace(...) router.replaceAll(...) // Popping the last pushed or replaced route router.pop() // Popping the last pushed or replaced route with parameters router.pop(parameters = parametersOf("number", "123"))
Type-safe routing
Based on Ktor Type-safe routing
First you have to put module
resources
as a dependency
@Resource("/articles") class Articles { @Resource("new") class New(val parent: Articles = Articles()) @Resource("{id}") class Id(val parent: Articles = Articles(), val id: Long) { @Resource("edit") class Edit(val parent: Id) } } val router = routing { install(Resources) push<Articles.New> { // handle push to this route only } replace<Articles> { // handle replace to this route only } replaceAll<Articles> { // handle replaceAll to this route only } // There is no use case for type-safe pop handler. Maybe in the future? } // Pushing a typed route router.push(Articles.New()) // Replacing a typed route router.replace(Articles()) // Pushing or Replacing a typed route with parameters router.push|replace|replaceAll(Articles.Id(id = 123)) // Popping the last pushed or replaced route router.pop()
Exception routing handler
Based on Ktor Status pages
First you have to put module
status-pages
as a dependency
val router = routing { install(StatusPages) { // Catch any exception (change to be specific if you need) exception<Throwable> { call, cause -> // exception handled during push, replace or pop routing } } push(path = "/path") { throw IllegalArgumentException("simulating an exception thrown on routing") } } // Pushing to simulate router.push(path = "/path")
Next steps
[ ] – Helper functions for each platform (Android, iOS, Web, Desktop, …)
[ ] – Support query parameters from external URI as Deep Link, Browser URL, etc
[ ] – More plugins like Session, CallLogging, etc
[ ] – Samples