HTML DSL
必要な依存関係: io.ktor:ktor-server-html-builder
コード例: html
HTML DSLは、kotlinx.htmlライブラリをKtorに統合し、HTMLブロックでクライアントに応答できるようにします。HTML DSLを使用すると、Kotlinで純粋なHTMLを記述したり、ビューに変数を補間したり、テンプレートを使用して複雑なHTMLレイアウトを構築したりできます。
依存関係の追加
HTML DSLはインストールを必要としませんが、ktor-server-html-builder
アーティファクトが必要です。次のようにビルドスクリプトに含めることができます。
HTMLをレスポンスとして送信
HTMLレスポンスを送信するには、必要なルート内で[respondHtml](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/respond-html.html)
メソッドを呼び出します。 以下の例は、サンプルHTML DSLと、クライアントに送信される対応するHTMLを示しています。
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>
<head>
<title>Ktor</title>
</head>
<body>
<h1>Hello from Ktor!</h1>
</body>
</html>
以下の例は、ユーザーから認証情報を収集するために使用されるHTMLフォームで応答する方法を示しています。
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>
<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>
フォームパラメータをサーバー側で受け取る方法については、フォームパラメータを参照してください。
kotlinx.htmlを使用したHTMLの生成について詳しく学ぶには、kotlinx.html wikiを参照してください。
テンプレート
プレーンなHTMLを生成することに加えて、Ktorは複雑なレイアウトを構築するために使用できるテンプレートエンジンを提供します。HTMLページの異なる部分にテンプレートの階層を作成できます。たとえば、ページ全体用のルートテンプレート、ページヘッダーとフッター用のチャイルドテンプレートなどです。Ktorはテンプレートを操作するための以下のAPIを公開しています。
- 指定されたテンプレートに基づいて構築されたHTMLで応答するには、
[respondHtmlTemplate](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/respond-html-template.html)
メソッドを呼び出します。 - テンプレートを作成するには、
[Template](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/-template/index.html)
インターフェースを実装し、HTMLを提供するTemplate.apply
メソッドをオーバーライドする必要があります。 - 作成されたテンプレートクラス内では、異なるコンテンツタイプ用のプレースホルダーを定義できます。
[Placeholder](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/-placeholder/index.html)
はコンテンツを挿入するために使用されます。[PlaceholderList](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/-placeholder-list/index.html)
は、複数回出現するコンテンツ(例:リスト項目)を挿入するために使用できます。[TemplatePlaceholder](https://api.ktor.io/ktor-server/ktor-server-plugins/ktor-server-html-builder/io.ktor.server.html/-template-placeholder/index.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つの部分に分割できます。
- ページヘッダー用のルートレイアウトテンプレートと、記事用のチャイルドテンプレート。
- 記事コンテンツ用のチャイルドテンプレート。
これらのレイアウトを段階的に実装してみましょう。
respondHtmlTemplate
メソッドを呼び出し、テンプレートクラスをパラメータとして渡します。この場合、これはTemplate
インターフェースを実装するLayoutTemplate
クラスです。
get("/") {
call.respondHtmlTemplate(LayoutTemplate()) {
// ...
}
}
このブロック内では、テンプレートにアクセスし、そのプロパティ値を指定できます。これらの値は、テンプレートクラスで指定されたプレースホルダーを置き換えます。次のステップでLayoutTemplate
を作成し、そのプロパティを定義します。
- ルートレイアウトテンプレートは次のようになります。
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
プロパティは記事コンテンツ用のチャイルドテンプレートを指定します。
- チャイルドテンプレートは次のようになります。
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)
}
}
}
このテンプレートはarticleTitle
、articleText
、list
プロパティを公開しており、これらの値はarticle
内に挿入されます。
- 値のリストをテンプレートとして提供するには、次の新しいクラスを作成します。
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>
要素で囲みます。
- これで、指定されたプロパティ値を使用して構築されたHTMLを送信する準備ができました。
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。