A Kotlin declarative DSL for Undertow routing configuration
You should use Underkow if you need to build a REST HTTP service using Undertow and you want to write code that is simple and effective without sacrificing best practices like dependency injection.
- A simple and clear DSL that can be used to configure Underkow routing using a declarative syntax (inspired by Ktor)
Coroutine based: every request is handled by a Kotlin coroutine, no need to mess with poolsCoroutine support is sill under heavy development in Kotlin, so it has been temporarily removed (see #254)- Completely asynchronous: every request is automatically marked as asynchronous, thus making the I/O thread immediately ready to receive a new request
- Composable: request handlers and filters can be declared independently and then chained together to create a filter chain
- Do not mess your classpath: Kotlin and Undertow are the only dependencies
The following is a simple example showing a minimal application. See the example directory for a more complete application.
fun main() {
// declare an Undertow server listening on TCP port 8080
undertow {
port = 8080
routing {
// declare a GET request requiring a path parameter
get("/users/{id}") { exchange ->
val id = exchange.getAttachment<PathTemplateMatch>(PathTemplateMatch.ATTACHMENT_KEY).parameters["id"]
exchange.responseSender.send("Hello world, this is user $id")
}
// declare a POST request that reads the full request body into a variable
post("/echo") { exchange ->
exchange.requestReceiver.receiveFullString { _, body ->
exchange.responseSender.send("Received body: $body")
}
}
// declare or inject a filter that will check for client credentials
val accessControlFilter : SuspendingHttpHandler = ...
// declare a group of paths prefixed by "/some/protected/path": each incoming request will be passed to the
// access control filter before being dispatched to its handler
path("/some/protected/path", accessControlFilter) {
get("/{id}") {
}
post("/{id}") {
}
put("/{id}") {
}
delete("/{id}") {
}
}
// declare or inject a filter that will log any request and response
val requestLoggingFilter : SuspendingHttpHandler = ...
filter(requestLoggingFilter) {
get("/something/{id}") {
}
post("/something/{id}") {
}
}
}
}
}
Fix: missing default exception handler propagation to every route.
Added support for defining a handler to override the default unhandled exception handler.
Added support for declaring Server Sent Event handlers
- Added support for handlers defined with no explicit path
- Added support for the definition of routes filtered by the same filter but having no common prefix
Fixed exception handler inheritance in nested routing builders.
Added support for OPTIONS HTTP verb
- Since coroutine support in Kotlin seems not to be stable yet, exchange dispatching has been modified to use the XNIO task pool by default and it can be overridden by the user.
- Builder options must be specified using DSL properties instead of DSL function arguments.
Fix: dependencies were not defined correctly and the user had to explicitly add them in its pom.xml
First release