Type-safe routing
Ktor 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.
Add dependencies
Add kotlinx.serialization
Given that resource classes should have @Serializable
behavior, you need to add the Kotlin serialization plugin as described in the Setup section.
Add Resources dependencies
To use Resources
, you need to include the ktor-server-resources
artifact in the build script:
Install Resources
To install the Resources
plugin to the application, pass it to the install
function in the specified module. The code snippets below show how to install Resources
...
... inside the
embeddedServer
function call.... inside the explicitly defined
module
, which is an extension function of theApplication
class.
Create resource classes
Each resource class should have the @Resource
annotation. Below, we'll take a look at several examples of resource classes - defining a single path segment, query and path parameters, and so on.
Resource URL
The example below shows how to define the Articles
class that specifies a resource responding on the /articles
path.
Resources with a query parameter
The Articles
class below has the sort
string property that acts as a query parameter and allows you to define a resource responding on the following path with the sort
query parameter: /articles?sort=new
.
Resources with nested classes
You can nest classes to create resources that contain several path segments. Note that in this case nested classes should have a property with an outer class type. The example below shows a resource responding on the /articles/new
path.
Resources with a path parameter
The example below demonstrates how to add the nested {id}
integer path parameter that matches a path segment and captures it as a parameter named id
.
As an example, this resource can be used to respond on /articles/12
.
Example: A resource for CRUD operations
Let's summarize the examples above and create the Articles
resource for CRUD operations.
This resource can be used to list all articles, post a new article, edit it, and so on. We'll see how to define route handlers for this resource in the next chapter.
Define route handlers
To define a route handler for a typed resource, you need to pass a resource class to a verb function (get
, post
, put
, and so on). For example, a route handler below responds on the /articles
path.
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.
Here are several tips on handling requests for each endpoint:
get<Articles>
This route handler is supposed to return all articles sorted according to the
sort
query parameter. For instance, this might be an HTML page or a JSON object with all articles.get<Articles.New>
This endpoint responds with a web form containing fields for creating a new article.
post<Articles>
The
post<Articles>
endpoint is supposed to receive parameters sent using a web form. Ktor also allows you to receive JSON data as an object using theContentNegotiation
plugin.get<Articles.Id>
This route handler is supposed to return an article with the specified identifier. This might be an HTML page showing an article or a JSON object with article data.
get<Articles.Id.Edit>
This endpoint responds with a web form containing fields for editing an existing article.
put<Articles.Id>
Similarly to the
post<Articles>
endpoint, theput
handler receives form parameters sent using a web form.delete<Articles.Id>
This route handler deletes an article with the specified identifier.
You can find the full example here: resource-routing.
Build links from resources
Besides using resource definitions for routing, they can also be used to build links. This is sometimes called reverse routing. Building links from resources might be helpful if you need to add these links to an HTML document created with HTML DSL or if you need to generate a redirection response.
The Resources
plugin extends Application
with the overloaded href method, which allows you to generate a link from a Resource
. For instance, the code snippet below creates a link for the Edit
resource defined above:
Since the grandparent Articles
resource defines the sort
query parameter with the default value new
, the link
variable contains:
To generate URLs that specify the host and protocol, you can supply the href
method with URLBuilder
. Additional query params can also be specified using the URLBuilder
, as shown in this example:
The link
variable subsequently contains:
Example
The example below shows how to add links built from resources to the HTML response:
You can find the full example here: resource-routing.