Skip to content

HTML DSL

必要な依存関係: io.ktor:ktor-server-html-builder

コード例: html

Native サーバー
Ktor supports Kotlin/Native and allows you to run a server without an additional runtime or virtual machine.
のサポート: ✅

HTML DSL は kotlinx.html ライブラリを Ktor に統合し、HTML ブロックを使用してクライアントにレスポンスを返すことを可能にします。HTML DSL を使用すると、Kotlin で純粋な HTML を記述したり、ビューに変数を挿入したり、テンプレートを使用して複雑な HTML レイアウトを構築したりできます。

依存関係の追加

HTML DSL はインストールの必要はありませんが、ktor-server-html-builder アーティファクトが必要です。以下のようにビルドスクリプトに含めることができます。

Kotlin
Groovy
XML

レスポンスで HTML を送信する

HTML レスポンスを送信するには、必要なルート内で respondHtml メソッドを呼び出します。 以下の例は、サンプルの HTML DSL と、クライアントに送信される対応する HTML を示しています。

kotlin
import io.ktor.server.application.*
import io.ktor.server.html.*
import io.ktor.http.*
import io.ktor.server.routing.*
import kotlinx.html.*

fun Application.module() {
    routing {
        get("/") {
            val name = "Ktor"
            call.respondHtml(HttpStatusCode.OK) {
                head {
                    title {
                        +name
                    }
                }
                body {
                    h1 {
                        +"Hello from $name!"
                    }
                }
            }
        }
    }
}
html
<html>
<head>
    <title>Ktor</title>
</head>
<body>
<h1>Hello from Ktor!</h1>
</body>
</html>

次の例は、ユーザーから認証情報を収集するために使用される HTML フォームでレスポンスを返す方法を示しています。

kotlin
get("/login") {
    call.respondHtml {
        body {
            form(action = "/login", encType = FormEncType.applicationXWwwFormUrlEncoded, method = FormMethod.post) {
                p {
                    +"Username:"
                    textInput(name = "username")
                }
                p {
                    +"Password:"
                    passwordInput(name = "password")
                }
                p {
                    submitInput() { value = "Login" }
                }
            }
        }
    }
}
html
<html>
<body>
<form action="/login" enctype="application/x-www-form-urlencoded" method="post">
    <p>Username:<input type="text" name="username"></p>
    <p>Password:<input type="password" name="password"></p>
    <p><input type="submit" value="Login"></p>
</form>
</body>
</html>

完全な例については、auth-form-html-dsl を参照してください。

サーバー側でフォームパラメータを受け取る方法の詳細については、フォームパラメータを参照してください。

kotlinx.html を使用した HTML 生成の詳細については、kotlinx.html wiki を参照してください。

HTML 部分テンプレートの送信

完全な HTML ドキュメントの生成に加えて、.respondHtmlFragment() 関数を使用して HTML フラグメントでレスポンスを返すこともできます。

HTML フラグメントは、HTMX のようなライブラリで使用される動的な更新など、完全な <html> ドキュメントを必要としない部分的なマークアップを返す場合に便利です。

kotlin
import io.ktor.server.application.*
import io.ktor.server.html.*
import io.ktor.http.*
import io.ktor.server.routing.*
import kotlinx.html.*

fun Application.module() {
    routing {
        get("/fragment") {
            call.respondHtmlFragment(HttpStatusCode.Created) {
                div("fragment") {
                    span { +"Created!" }
                }
            }
        }
    }
}
html
<div class="fragment">
    <span>
        Created!
    </span>
</div>

この関数は .respondHtml() と同様に動作しますが、ルート HTML 要素を追加せずに、ビルダー内で定義したコンテンツのみをレンダリングします。

テンプレート

単純な HTML の生成に加えて、Ktor は複雑なレイアウトを構築するために使用できるテンプレートエンジンを提供します。HTML ページのさまざまな部分に対してテンプレートの階層を作成できます。たとえば、ページ全体のリミットテンプレート、ページヘッダーとフッターの子テンプレートなどです。Ktor はテンプレートを操作するための以下の API を提供しています。

  1. 指定されたテンプレートに基づいて構築された HTML でレスポンスを返すには、respondHtmlTemplate メソッドを呼び出します。
  2. テンプレートを作成するには、Template インターフェースを実装し、HTML を提供する Template.apply メソッドをオーバーライドする必要があります。
  3. 作成されたテンプレートクラス内で、さまざまなコンテンツタイプのプレースホルダーを定義できます。
    • Placeholder はコンテンツを挿入するために使用されます。PlaceholderList は、複数回表示されるコンテンツ(例:リストアイテム)を挿入するために使用できます。
    • TemplatePlaceholder は、子テンプレートを挿入してネストされたレイアウトを作成するために使用できます。

テンプレートを使用して階層的なレイアウトを作成する方法のを見てみましょう。次のような HTML があると仮定します。

html
<body>
<h1>Ktor</h1>
<article>
    <h2>Hello from Ktor!</h2>
    <p>Kotlin Framework for creating connected systems.</p>
    <ul>
       <li><b>One</b></li>
       <li>Two</li>
    </ul>
</article>
</body>

このページのレイアウトを 2 つの部分に分けることができます。

  • ページヘッダー用のルートレイアウトテンプレートと、記事用の子テンプレート。
  • 記事コンテンツ用の子テンプレート。

これらのレイアウトをステップバイステップで実装してみましょう。

  1. respondHtmlTemplate メソッドを呼び出し、パラメータとしてテンプレートクラスを渡します。この例では、Template インターフェースを実装する必要がある LayoutTemplate クラスです。

    kotlin
    get("/") {
        call.respondHtmlTemplate(LayoutTemplate()) {
            // ...
        }
    }

    ブロック内では、テンプレートにアクセスしてそのプロパティ値を指定できます。これらの値は、テンプレートクラスで指定されたプレースホルダーを置き換えます。次のステップで LayoutTemplate を作成し、そのプロパティを定義します。

  2. ルートレイアウトテンプレートは以下のようになります。

    kotlin
    class LayoutTemplate: Template<HTML> {
        val header = Placeholder<FlowContent>()
        val content = TemplatePlaceholder<ArticleTemplate>()
        override fun HTML.apply() {
            body {
                h1 {
                    insert(header)
                }
                insert(ArticleTemplate(), content)
            }
        }
    }

    このクラスは 2 つのプロパティを公開しています。

    • header プロパティは、h1 タグ内に挿入されるコンテンツを指定します。
    • content プロパティは、記事コンテンツ用の子テンプレートを指定します。
  3. 子テンプレートは以下のようになります。

    kotlin
    class ArticleTemplate : Template<FlowContent> {
        val articleTitle = Placeholder<FlowContent>()
        val articleText = Placeholder<FlowContent>()
        val list = TemplatePlaceholder<ListTemplate>()
        override fun FlowContent.apply() {
            article {
                h2 {
                    insert(articleTitle)
                }
                p {
                    insert(articleText)
                }
                insert(ListTemplate(), list)
            }
        }
    }

    このテンプレートは articleTitlearticleTextlist プロパティを公開しており、それらの値は article 内に挿入されます。

  4. テンプレートとして値のリストを提供するには、次の新しいクラスを作成します。

    kotlin
    class ListTemplate : Template<FlowContent> {
        val item = PlaceholderList<UL, FlowContent>()
        override fun FlowContent.apply() {
            if (!item.isEmpty()) {
                ul {
                    each(item) {
                        li {
                            if (it.first) {
                                b {
                                    insert(it)
                                }
                            } else {
                                insert(it)
                            }
                        }
                    }
                }
            }
        }
    }

    このテンプレートは、PlaceholderList クラスを使用して、提供されたアイテムから順序なしリスト (UL) を生成します。また、強調のために最初のアイテムを <b> 要素で囲みます。

  5. これで、指定されたプロパティ値を使用して構築された HTML を送信する準備が整いました。

    kotlin
    get("/") {
        call.respondHtmlTemplate(LayoutTemplate()) {
            header {
                +"Ktor"
            }
            content {
                articleTitle {
                    +"Hello from Ktor!"
                }
                articleText {
                    +"Kotlin Framework for creating connected systems."
                }
                list {
                    item { +"One" }
                    item { +"Two" }
                }
            }
        }
    }

完全な例はこちらで見つけることができます: html-templates