Controllers
This framework allows to create APIs by defining and implementing controller classes. In contrast to Spring MVC, you cannot use this framework to dynamically render HTML pages in an MVC style project, so this is just another flavor of defining a web API.
Hosting an API
The following example shows how an API controlling an IoT device could look like when implemented using the controller framework.
The functions of the controller class will automatically be translated into paths that can be called by the client.
import org.genhttp.engine.internal.Host
import org.genhttp.modules.apibrowsing.addRedoc
import org.genhttp.modules.controllers.ControllerAction
import org.genhttp.modules.controllers.FromPath
import org.genhttp.modules.controllers.addController
import org.genhttp.modules.layouting.Layout
import org.genhttp.modules.openapi.addOpenApi
import org.genhttp.modules.practices.defaults
import org.genhttp.modules.reflection.Method
import org.genhttp.modules.security.CorsPolicy
suspend fun main() {
val api = Layout.create()
.addController<IotController>("device")
.add(CorsPolicy.permissive())
.addOpenApi() // http://localhost:8080/openapi.json
.addRedoc() // http://localhost:8080/redoc/
Host.create()
.handler(api)
.defaults()
.development()
.run()
}
data class DeviceInfo(val name: String = "Thermostat", val online: Boolean = true)
data class DeviceFieldInfo(val id: Int, val value: Double = 21.5)
class IotController {
// GET http://localhost:8080/device/
fun index(): DeviceInfo = DeviceInfo()
// GET http://localhost:8080/device/field/4711/
fun field(@FromPath fieldId: Int): DeviceFieldInfo = DeviceFieldInfo(fieldId)
// POST http://localhost:8080/device/restart/
@ControllerAction(Method.Post)
fun restart(): DeviceInfo = DeviceInfo()
}Every public function declared by the controller class becomes an action, handling GET and HEAD
requests unless @ControllerAction specifies other methods. As functions in Kotlin are public by
default, declare helper functions of a controller as private.
addController<T>() creates a single instance of the controller that handles all requests, so
the class needs a constructor without parameters. To construct the controller yourself, add it
with add("device", Controller.from(IotController())).
URL Patterns
The following table shows the rules that are applied to map an URL:
| Function | Endpoint |
|---|---|
fun index() | /controller/ |
fun action() | /controller/action/ |
fun action(@FromPath id: Int) | /controller/action/:id/ |
fun action(id: Int) | /controller/action/?id=:id |
fun longAction() | /controller/long-action/ |
Further Resources
The following capabilities are shared by various application frameworks: