-
Notifications
You must be signed in to change notification settings - Fork 3
Type‐safe routing
Kotlin Routing provides the Resources Plugin that allows you to implement type-safe routing. To accomplish this, you need to create a class that should act as a typed route and then annotate this class using the @Resource
keyword. Note that the @Resource
annotation has @Serializable
behavior provided by the kotlinx.serialization
library.
sourceSets {
commonMain.dependencies {
implementation("dev.programadorthi.routing:resources:$version")
}
}
To install the Resources plugin to the application, pass it to the install function. The code snippets below show how to install Resources...
val router = routing {
install(Resources)
// ...
}
The same as oficial docs Create resource classes
To define a route handler for a typed resource, you need to pass a resource class to a handle function. For example, a route handler below responds on the /articles
path.
@Resource("/articles")
class Articles()
val router = routing {
install(Resources)
handle<Articles> { articles ->
// handle any call to Articles
}
}
The example below shows how to define route handlers for the Articles resource created in Example: A resource for CRUD operations. Note that inside the route handler you can access the Article as a parameter and obtain its property values.
val router = routing {
install(Resources)
handle<Articles> { article ->
// Get all articles ...
}
handle<Articles.New> {
// Show a page with fields for creating a new article ...
}
handle<Articles>(method = RouteMethod("SAVE")) {
// Save an article ...
}
handle<Articles.Id> { article ->
// Show an article with id ${article.id} ...
}
handle<Articles.Id.Edit> { article ->
// Show a page with fields for editing an article ...
}
handle<Articles.Id>(method = RouteMethod("UPDATE")) { article ->
// Update an article ...
}
handle<Articles.Id>(method = RouteMethod("DELETE")) { article ->
// Delete an article ...
}
}
The same as oficial docs Build links from resources
router.call(Articles())
router.callWithBody(Articles(), bodyTypeInstance)
val router = routing { }
router.canHandleByResource<Articles.Id.Edit>()
// or
router.canHandleByResource<Articles.Id.Edit>(method = ...)
val router = routing {
handle("/hello") {
call.redirectTo(resource = Articles.Id(id = 456))
// or
call.redirectTo(resource = Articles.Id(id = 456), method = ...)
}
}
Routes can be registered on demand avoiding have to declare all of them on Routing instantiation:
val router = routing { }
// on demand
router.handle<Articles.Id.Edit>(...) {
// ...
}
val router = routing { }
router.unregisterResource<Articles>()
Maybe you have distinct features that have it own lifecycle and know the parent Routing only. This create a hierarchy like a B-Tree that root and leaf knows each other but siblings don't.
@Resource("/parent")
class ParentRouting {
@Resource("/child")
class ChildRouting(val parent: ParentRouting = ParentRouting()) {
@Resource("/destination")
class Destination(val parent: ChildRouting = ChildRouting())
}
}
val applicationRouter = routing(rootPath = "/parent") { }
val featureRouter = routing(rootPath = "/child", parent = applicationRouter) {
handle<ParentRouting.ChildRouting.Destination> {
// ...
}
}
// routing inside feature
featureRouter.call(resource = ParentRouting.ChildRouting.Destination())
// routing from application to feature
applicationRouter.call(resource = ParentRouting.ChildRouting.Destination())