Ktor on Google AppEngine from Zero to Hero part 2

Peter Nagy
3 min readNov 3, 2022

Routing

When you want to create a backend you need to handle several urls. Like user related urls, or customer related, or product specific urls. The origin idea is we want to use url(s) which make sense and logical. For example if we want to handle user settings then we want to this kind of urls:

/user/username/settings

This format is logical because nobody will remember if we are using random urls. There is an information about what will happen when we will call the url. And what is more important we want to save our time and reduce the copy paste code or code duplications.

Routing is a core plugin in Ktor. What does it mean ? We do not have to install it (or we can use it without install).

This plugin is handle the incoming requests (and outcoming responses). With help of this plugin we are able to define rules how to handle the incoming requests.

Let’s see how looks like in the practice. In part1 we used this:

routing {
get("/") {
call.respondText("Hello, world!")
}
}

Yes! There is a lambda it is the routing. We will handle the incoming HTTP GET request(s) and we will response with a text message.

We are able to handle GET, POST, PUT, DELETE, HEAD, and so on requests. This is standard types of Http requests. We can handle the request type like this:

route("/hello", HttpMethod.Get) {
handle {
call.respondText("Hello")
}
}

I liked it more the shorter form:

get("/hello") {
call.respondText { "Hello" }
}

The both code are equivalent. In the handle block we are able to get the ApplicationCall class which might be important later. There is a context and we can reach the Application class too.

Let’s see some example how can we use routing in the urls.

We can use fix url:

get("/hello") {
call.respondText { "Hello" }
}

Url is fix, no parameter.

We can use parameters:

get("/say/hello/{name}") {
val name = call.parameters["name"]
call.respondText { "Hello $name" }
}

Here {name} is a parameter we can get it from parameters and we can use it to generate a response.

We can use wildcard in the url:

get("/test/*") {
....
}

Wildcard means same like in the local computer when we want to select a file. This route will handle for example the /test/example url. There is no any parameter but we can get the path from the request.

call.request.path()

We can use tailcard:

get("/test/{param...}") {
val params = call.parameters.getAll("param")
call.respondText { "Params caught: ${params?.joinToString(",")}" }
}

This is very similar to the wildcard cases hover there is an option to use a param. We can get all parameter. GetAll will return a list of strings. If the url is: /test/one/two then we will get back { “one”, “two” }.

We can use optional parameter:

get("/user/{login?}") {
val param = call.parameters["login"]
call.respondText("Hello: $param")
}

It means this route will handle /user and /user/peter too. There is one important thing, optional parameter must be at end of the path.

We can grouping the routes:

route("/customer") {
get {

}
post {

}
}
route("/order") {
get {

}
get("/{id}") {

}
}

In the routing block we can use route block and it could have separate handler(s).

Or we can use nested routes:

route("/order") {
route("/shipment") {
get {

}
post {

}
}
}

If we want to separate the route(s) in different files, then we can write extension functions:

fun Route.talkRoute() {
get("/goodbye") {
call.respondText("Bye-Bye")
}
}
routing {
talkRoute()
}

This could help separate the endpoints into different files. We can separate the different functionality in a different class or file.

Trace route:

Ktor allows you to log information about route matches to determine why some routes are not being executed. To enable tracing, call the trace function inside the routing block as follows:

routing {     trace { application.log.trace(it.buildText()) } }

If you want to see a working demo you can find it in my GitHub page:

Thanks for reading my article! If you found this post useful? Kindly tap the 👏 button below and follow :) .

--

--