# KTOR as a backend - part 1

*This article is the first part of the three-part series that will smoothly introduce* ***KTOR as a backend*** *that can be built in a blink of an eye.*

I am sure that if you are an Android Developer with some good background, experience in Kotlin, and some fun with [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html) — you don’t think of yourself as a full stack dev — but you should! All the good practices, well-known libraries, and functional ways of programming can be transferred from Android to a different domain and still make things happen.

In this article, I would like to introduce you to [Ktor](https://ktor.io/) as a backend for your application. It is a brilliant and ready-to-go solution that can be built in a blink of an eye. The Ktor itself provides the best definition:  

> *Ktor is a framework to easily build connected applications — web applications, HTTP services, mobile and browser applications. Modern connected applications need to be asynchronous to provide the best experience to users, and Kotlin coroutines provide excellent facilities to do it easily and straightforwardly.*

The project is available on [GitHub](https://github.com/mkonkel/KtorBackend) repo.

---

# **Let’s create a project**

For example, we will create a simple Game Shop where users can view available games and place an order.

With [IntelliJ](https://www.jetbrains.com/idea/) is very easy to bootstrap your project as the IDE got a dedicated plugin to create the Ktor project.

Open IntelliJ and follow the steps:

* Run the project Wizard `New Project` or `File | New | project`
    
* Choose **Ktor** from the **generators** section
    
* Fill the project details with desired data
    

![IntelliJ, New Project tab](https://miro.medium.com/v2/resize:fit:700/1*4Mh80e7gf6l0Pv0Nq9aflg.png align="left")

On the next page, we can install some plugins that will be included in the project.  
In the beginning, we need only one [**Routing**](https://ktor.io/docs/routing-in-ktor.html), which is the core Ktor plugin responsible for handling requests and responses in the server application.

![](https://miro.medium.com/v2/resize:fit:700/1*cJAHhz3lhnzA3Xdubz0J3w.png align="left")

Click **Create** and wait for the build to end. You can see the project structure and an `Application.kt` on the left pane. Inside the file, we’ve got the **embeddedServer** function responsible for project configuration and running the application.

```kotlin
fun main() {
   embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
       configureRouting()
   }.start(wait = true)
}
```

![](https://miro.medium.com/v2/resize:fit:700/1*qc98HF1x2tcFOfWTyS0yHw.png align="left")

The **configureRouting** extension function contains the routing information.

```kotlin
fun Application.configureRouting() {
   routing {
       get("/") {
           call.respondText("Hello World!")
       }
   }
}
```

![](https://miro.medium.com/v2/resize:fit:628/1*HbnRzPWOTzYxyxiLYhLQAw.png align="left")

The routing with address “/” will lead us to the blank page with the “Hello World”. To check if this works, we need to run our application. Go to `Application.kt` and click the **Run Application** option from the context menu.

![](https://miro.medium.com/v2/resize:fit:700/1*XaChsM4yWz9dsc3cPT-nGQ.png align="left")

After the successful execution, we can see in the terminal window that the app is started on `http://localhost`, with port `8080`.

![](https://miro.medium.com/v2/resize:fit:700/1*xTER6A4zKw5McH1cK1xbwg.png align="left")

With the working application, we can now go a bit further and create some basic API for our game shop.

# **Creating Routes — games endpoint**

With our project up and running, we should think about some REST API for our Game Shop, to do this, we need to use the [Routing](https://ktor.io/docs/routing-in-ktor.html) plugin. The plugin handles all incoming requests, provides endpoints, and serves the response. To do so, we need it in the application.

Let’s go to the **configureRouting** function and create CRUD endpoints for games, we can start with a route for fetching all the games in the shop. To do this, we need to define the handler.

```kotlin
route("/games") {
    get {
        call.respondText("Games")
    }
}
```

When we run our application and try to invite the `GET` request on the address `0.0.0.0:8080/games`*,* we should receive the following response. IntelliJ gives us a great tool for such a call — HTTP Request.

![](https://miro.medium.com/v2/resize:fit:700/1*qKCAlZNdjwIxWIqI5cM_gQ.png align="left")

```kotlin
### GET - get Games List
GET http://0.0.0.0:8080/games
Content-Type: application/json
```

![](https://miro.medium.com/v2/resize:fit:700/1*ccySGbbNa9RV5KsK_hMCXQ.png align="left")

That concludes our first endpoint with functional requests and responses. However, this implementation is somewhat simplistic and could be improved. We should enhance our codebase to align with standards expected in a professional application.

We can organize our code, add some modules, classes, and a bit of abstraction. To start, we can divide our code into well-structured packages.

![](https://miro.medium.com/v2/resize:fit:700/1*WWGTuFnuZbYkjylUQVKDag.png align="left")

The **data** package will hold the request-response objects. With the usage of the [**kotlinx.serialization**](https://kotlinlang.org/docs/serialization.html), we can create a data class that will be used in our endpoint

```kotlin
@Serializable
data class Game(
   val id: String,
   val name: String,
   val price: Float,
   val genre: String
)
```

Then in the **domain** package, we can create a **GamesRepository** interface and its implementation, for now, it will hold data in a local mutable list and simulate storage.

```kotlin
interface GamesRepository {
   fun getGames(): List<Game>
}

internal class GamesRepositoryImpl : GamesRepository {
   private val games: MutableList<Game> = mutableListOf()

   override fun getGames(): List<Game> {
       return games
   }
}
```

To be able to access the repository from any point in the app, we can create an object that will be providing the repo.

```kotlin
object GamesFeature {
   val repository: GamesRepository = GamesRepositoryImpl()
}
```

With all pieces configured, we can start working with the presentation layer, which in our case, will not include any UI but only the Routing. We can create an extension function with games-specific routing.

```kotlin
fun Route.gamesRouting() {
   route("/games") {
       val gamesRepo = GamesFeature.repository


       get {
           val games = gamesRepo.getGames()
           call.respondText(text = games.toString(), status = HttpStatusCode.OK)
       }
```

If we rerun our test request, we will see that the app returns an empty array — which is correct since we didn’t add any games yet! To do so, we need to define a request data class, a repository method for adding the new game to the collection, and a new endpoint that will allow us to **POST** a game.

```kotlin
@Serializable
data class GameRequest(
   val name: String,
   val price: String,
   val genre: String
)

interface GamesRepository {
   fun addGame(game: GameRequest) : Game
}

internal class GamesRepositoryImpl : GamesRepository {
   override fun addGame(game: GameRequest): Game {
      return Game(
          id = UUID.randomUUID().toString(),
          name = game.name,
          price = game.price.toFloat(),
          genre = game.genre
       )
       .also { games.add(it) }
}

fun Route.gamesRouting() {
   route("/games") {
         post {
             val gameRequest = call.receive<GameRequest>()
             val game = gamesRepo.addGame(gameRequest)
             call.respond(
                   status = HttpStatusCode.Created,
                   message = game
             )
          }
}
```

There is one new thing in the code above `call.receive<GameRequest>()` this will allow us to retrieve the body of a POST request, which can now be passed further to a repository.

We can easily handle the response using a Ktor plugin **ContentNegotiation** and [**Serialization**](https://ktor.io/docs/serialization.html). To do so, we can create another extension function and use it in our `Application.kt` file.

```kotlin
fun main() {
   embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
       …
       configureSerialization()
   }.start(wait = true)
}
```

We can also improve the **GET** games endpoint to handle fetching the game list more smoothly.

```kotlin
get {
   val games = gamesRepo.getGames()

   if (games.isNotEmpty()) {
       call.respond(games)
   } else {
       call.respondText(text = "There are no games in our shop yet...", status = HttpStatusCode.OK)
   }
}
```

With all of that, we can try to make some requests and see if everything works fine.

```kotlin
### POST - Add game
POST http://0.0.0.0:8080/games
Content-Type: application/json
{
 "name": "Doom 2",
 "price": "10.00",
 "genre": "FPS"
}

### GET - get Games List
GET http://0.0.0.0:8080/games
Content-Type: application/json
```

Running those two requests should create a game and return the list of games. The complete example can be found on [GitHub](https://github.com/mkonkel/KtorBackend/blob/master/src/main/kotlin/pl/mkonkel/features/games/presentation/GamesRoutes.kt).

The routing plugin supports all the verbs, such as **PUT**, **DETELE, HEAD** and others. It can also provide a way to specify path parameters `/games/{id},` which can be obtained with a `call.parameters[“id”]` function or query parameters **/**`games?genere=FPS` available with `call.request.queryParameters[“genre”]` so we can easily model our games endpoint

```kotlin
get("{id?}") {
   val id = call.parameters["id"] ?: return@get call.respondText(
       text = "Id is required",
       status = HttpStatusCode.BadRequest
   )

   val game = gamesRepo.getGame(id) ?: return@get call.respondText(
       text = "Game with $id does not exist",
       status = HttpStatusCode.NotFound
   )

   call.respond(game)
}
```

As you can see, with the `respondText` and `respond` methods, we are providing the response to the client, thanks to the **kotlinx.serialziation** and **content negotiation** plugins, the user will receive the data in JSON format. We can also provide response codes such as 200, 204, 400, 500, etc.

# **Type safe routing — orders endpoint**

With some games in the shop, it would be nice to allow users to buy a game, to do so they need to place an order. From the code point of view, the design will be the same — request, response classes, repository, and routing. But to be honest, fetching parameters with `call.parameters[“id”]` can be tricky and requires some work — we can be smarter and use **the Resources** plugin that provides type-safe routing with the support of query parameters and path parameters.

First, we need to add the dependency into our gradle file and install the plugin in our application.

```kotlin
implementation("io.ktor:ktor-server-resources:$ktor_version")

fun main() {
   embeddedServer(Netty, port = 8080, host = "0.0.0.0") {
       install(Routing)
       install(Resources)
```

Then with the given structure, let’s inspect the **OrdersResources**.

Orders allow us to structure the code in a more convenient and easily manageable way, all resources needed to be annotated with `@Serialziation` and `@Resources`. Resources support nested classes that can indicate that our paths belong to the exact origin. The nested class needs to include its parent in the constructor parameter.

```kotlin
@Serializable
@Resource("/orders")
class OrdersResources(val genre: String? = null) {

   @Serializable
   @Resource("{id}")
   class Id(val parent: OrdersResources = OrdersResources(), val id: String) {
       @Serializable
       @Resource("edit")
       class Edit(val parent: Id, val name: String)

       @Serializable
       @Resource("address")
       class Address(val parent: Id)
   }
}
```

What we’ve done here is defining the endpoints for the orders feature, going from top to bottom, we have:

* `/orders` *path for fetching the list of otters with optional query parameter price that can be used for filtering.*
    
* `/orders` *path for creating an order*
    
* `/orders/{id}` *path for fetching the details of one order*
    
* `/orders/(id}` path for deleting the order
    
* `/orders/(id}` *path for editing the order*
    
* `/orders/{id}/address` *path for fetching the delivery address*
    

With such defined resources, we can go to our routing class and use the created paths — we need to visit the `OrdersRoute.kt`**.** In the beginning, we should start with something simple — a list of all games.

```kotlin
get<OrdersResources> {
   val orders = repo.getOrders()
   call.respond(orders)
}
```

That’s all, instead of writing the path, we are using the resources class.

Now let's implement fetching the order by its id.

```kotlin
get<OrdersResources.Id> { request ->
   val order = repo.getOrder(request.id)

   order?.let { call.respond(it) } ?: call.respondText(
       status = HttpStatusCode.BadRequest,
       text = "No such order! OrderId: ${request.id}"
   )
}
```

In lambda, we are able to access the **request** with the usage of **resources** the request handler is aware of the shape processing call and can easily access the **id** parameter and perfectly knows that its type is a String. There is nothing more left than asking the repo for an order with a given id and providing proper responses **200** with data or **400** if the order does not exist.

```kotlin
post<OrdersResources> {
   val orderRequest = call.receive<OrderRequest>()
   val newOrder = repo.addOrder(orderRequest)
   call.respond(newOrder)
}

delete<OrdersResources.Id> { request ->
   try {
       repo.delete(request.id)
       call.respond(
           status = HttpStatusCode.NoContent,
           message = "Order deleted"
       )
   } catch (e: Exception) {
       call.respondText(
           status = HttpStatusCode.BadRequest,
           text = "No such order! OrderId: ${request.id}"
       )
   }
}
```

Creating and deleting the orders works the same way, the interesting part is when we are trying to obtain only the delivery address.

```kotlin
get<OrdersResources.Id.Address> { request ->
   val address = repo.getOrder(request.parent.id)?.address
   address?.let { call.respond(it) } ?: call.respondText("No such order! OrderId: ${request.parent.id}")
}
```

If we want to obtain the **id** from the path, we need to call the **parent** nested class for it, and after that, we can fetch the **address** from the rest of the request path.

Using the query param is also really simple, let’s filter out orders based on their price.

```kotlin
get<OrdersResources> { request ->
   val price = request.price ?: 0
   val orders = repo.getOrders()
       .filter { it.price > price }
  
   call.respond(orders)
}
```

Now we can write some HTTP Requests and check if our code is working as expected. Running requests one by one, you should be able to go through the whole process.

```http
### POST - add game
POST http://0.0.0.0:8080/games
Content-Type: application/json

{
 "name": "Doom 2",
 "price": "10.00",
 "genre": "FPS"
}

> {%
   client.global.set("game_id", response.body.id);
%}

### POST - create an order
POST http://0.0.0.0:8080/orders
Content-Type: application/json

{
 "games" : [{{game_id}}],
 "address": "Street 12, City 11-222"
}

### GET - get all orders with price greater than 20
GET http://0.0.0.0:8080/orders?price=20
Content-Type: application/json

### GET - get all orders
GET http://0.0.0.0:8080/orders
Content-Type: application/json

> {%
   client.global.set("order_id", response.body[0].id);
%}

### GET - get single order by ID
GET http://0.0.0.0:8080/orders/{{order_id}}

Content-Type: application/json

### GET - get order address
GET http://0.0.0.0:8080/orders/{{order_id}}/address
Content-Type: application/json

### DELETE - deleto order
DELETE http://0.0.0.0:8080/orders/{{order_id}}
Content-Type: application/json
```

We’ve reached the end of the first part of the article. I hope you’ve enjoyed it and you can’t wait for more.

*This post was originally published on* [*Speednet blog*](https://speednet.pl/blog/ktor-as-a-backend/?utm_source=medium&utm_medium=referral&utm_campaign=ktor) *on 10.11.2022*
