Pages

The pages module allows the server to generate HTML pages (e.g. error messages or the directory listing) and can be used to render custom pages from a template, using Pebble as a rendering engine. Support for rendering websites in genhttp-kt is minimalistic, so you should not use this for a website project.

GenHTTP renders templates with Cottle, which does not exist on the JVM, so genhttp-kt uses Pebble instead. Pebble is configured to behave like Cottle: values are not escaped automatically, variables that are not part of the model render as empty text, and white space is kept as it is.

Page Rendering

The following example will show you how to use a Pebble template file to generate a web page with dynamic content via genhttp-kt.

Source

Kotlin
import org.genhttp.api.content.io.Resource
import org.genhttp.api.protocol.Request
import org.genhttp.engine.internal.Host

import org.genhttp.modules.functional.*
import org.genhttp.modules.io.*
import org.genhttp.modules.pages.Renderer
import org.genhttp.modules.pages.getPage
import org.genhttp.modules.practices.defaults

suspend fun main() {
    val template = Renderer.from(Resource.fromClasspath("Template.html").build())

    val app = Inline.create()
        .get { request: Request ->
            val data = mapOf("users" to getUsers())

            request.getPage(template.render(data))
        }

    Host.create()
        .handler(app)
        .defaults()
        .development()
        .run()
}

data class User(val id: Int, val name: String)

fun getUsers(): List<User> = listOf(User(1, "Some User"))

Template.html

Pebble
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Users</title>
</head>
<body>

<table>
    <tr>
        <th>ID</th>
        <th>Name</th>
    </tr>
    {% for user in users %}
    <tr>
        <td>{{ user.id }}</td>
        <td>{{ user.name | escape }}</td>
    </tr>
    {% endfor %}
</table>

</body>
</html>

The template is read from the classpath (src/main/resources/Template.html) and compiled once; if the resource changes, it is compiled again on the next rendering. The model is a Map<String, Any?>: Pebble reads the properties of the objects in it, such as user.name of a data class, through their getters. As the output is not escaped automatically, apply the escape filter to values that may contain HTML, such as the name of a user.

Server-Styled Pages

Renderer.server is a built-in renderer using the same theme as the server’s own error pages and directory listings, so you can render a simple page without shipping a template of your own:

Kotlin
val app = Inline.create()
    .get { request: Request ->
        val page = Renderer.server.render("Maintenance", "<p>We'll be back shortly.</p>")

        request.getPage(page)
    }

Neither the title nor the content are escaped by the renderer; escaped() escapes a string for HTML if it contains user input (name.escaped()).