Templates #
Direktif templates Caddy memungkinkan file HTML yang disajikan oleh file_server untuk mengandung template actions — logika server-side sederhana seperti menyisipkan nilai variabel, include file lain, kondisi if/else, dan loop. Ini menggunakan syntax Go template (text/template) dan memungkinkan pembuatan halaman dinamis tanpa backend terpisah.
Ini bukan pengganti framework web, tapi sangat berguna untuk situs statis yang membutuhkan sedikit dinamisme: include komponen yang reusable, menampilkan informasi server, atau halaman error yang kaya konten.
Mengaktifkan Templates #
example.com {
root * /var/www/html
# Aktifkan template rendering
templates
file_server
}
Sekarang setiap file HTML yang disajikan bisa menggunakan template syntax.
Syntax Dasar Template #
<!-- Template action menggunakan {{ dan }} -->
<!-- Sisipkan nilai placeholder Caddy -->
<p>Request dari: {{.RemoteIP}}</p>
<p>Host: {{.Host}}</p>
<p>Path: {{.URI}}</p>
<p>Waktu sekarang: {{now | date "2006-01-02 15:04:05"}}</p>
<!-- Variabel -->
{{$name := "World"}}
<h1>Hello, {{$name}}!</h1>
<!-- Kondisi -->
{{if eq .Host "example.com"}}
<p>Ini adalah production site</p>
{{else}}
<p>Ini bukan production</p>
{{end}}
<!-- Loop -->
{{$items := slice "Apple" "Banana" "Cherry"}}
<ul>
{{range $items}}
<li>{{.}}</li>
{{end}}
</ul>
Variabel Template yang Tersedia #
Variabel Nilai
──────────────────────────────────────────────────────────────────
.RemoteIP IP address client
.Host Hostname dari request
.URI URI lengkap (path + query)
.Method HTTP method (GET, POST, dll.)
.Proto Protokol (HTTP/1.1, HTTP/2)
.Scheme http atau https
.Header.NAMA Nilai header request tertentu
.Cookie.NAMA Nilai cookie tertentu
.Req Objek *http.Request lengkap
Include — Partial Templates #
Fitur yang paling berguna: include komponen yang reusable ke banyak halaman:
Struktur direktori:
/var/www/html/
├── index.html
├── about.html
├── contact.html
└── partials/
├── header.html
├── footer.html
└── nav.html
<!-- partials/header.html -->
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{block "title" .}}Website{{end}}</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<!-- partials/nav.html -->
<nav>
<a href="/" {{if eq .URI "/"}}class="active"{{end}}>Home</a>
<a href="/about" {{if eq .URI "/about"}}class="active"{{end}}>About</a>
<a href="/contact" {{if eq .URI "/contact"}}class="active"{{end}}>Contact</a>
</nav>
<!-- partials/footer.html -->
<footer>
<p>© {{now | date "2006"}} Example.com</p>
<p>Powered by Caddy Web Server</p>
</footer>
</body>
</html>
<!-- index.html -->
{{template "partials/header.html" .}}
{{define "title"}}Home - Example.com{{end}}
{{template "partials/nav.html" .}}
<main>
<h1>Selamat Datang</h1>
<p>Halaman ini dirender oleh Caddy Templates.</p>
<p>Kamu mengakses dari IP: {{.RemoteIP}}</p>
</main>
{{template "partials/footer.html" .}}
Template untuk Halaman Error Kustom #
Salah satu use case terbaik templates: halaman error yang informative:
example.com {
root * /var/www/html
templates
file_server
handle_errors {
rewrite * /errors/{err.status_code}.html
templates
file_server { root /var/www/html }
}
}
<!-- /var/www/html/errors/404.html -->
<!DOCTYPE html>
<html lang="id">
<head>
<title>404 - Halaman Tidak Ditemukan</title>
<style>
body { font-family: sans-serif; text-align: center; padding: 50px; }
.code { font-size: 120px; color: #ccc; font-weight: bold; }
</style>
</head>
<body>
<div class="code">{{placeholder "http.error.status_code"}}</div>
<h1>Halaman Tidak Ditemukan</h1>
<p>URL yang kamu cari: <strong>{{.URI}}</strong></p>
<p>tidak ditemukan di server ini.</p>
<a href="/">← Kembali ke Beranda</a>
<!-- Tampilkan detail hanya di development -->
{{if eq .Host "localhost"}}
<pre style="text-align:left; background:#f5f5f5; padding:20px; margin-top:30px">
Error: {{placeholder "http.error.message"}}
Status: {{placeholder "http.error.status_code"}}
</pre>
{{end}}
</body>
</html>
Fungsi Template Bawaan Caddy #
Caddy menambahkan fungsi-fungsi tambahan ke Go template:
<!-- Tanggal dan waktu -->
{{now | date "2006-01-02"}} <!-- 2024-01-15 -->
{{now | date "02 Jan 2006"}} <!-- 15 Jan 2024 -->
{{now | date "15:04:05"}} <!-- 14:30:00 -->
<!-- String manipulation -->
{{"Hello World" | lower}} <!-- hello world -->
{{"hello world" | upper}} <!-- HELLO WORLD -->
{{" trimmed " | trimSpace}} <!-- trimmed -->
{{split "a,b,c" ","}} <!-- [a b c] -->
{{join (slice "a" "b" "c") ","}} <!-- a,b,c -->
<!-- URL encoding -->
{{"hello world" | pathEscape}} <!-- hello%20world -->
{{"hello=world" | queryEscape}} <!-- hello%3Dworld -->
<!-- HTML escaping (otomatis dalam {{ }}) -->
{{"<script>" | html}} <!-- <script> -->
<!-- Matematika -->
{{add 5 3}} <!-- 8 -->
{{sub 10 3}} <!-- 7 -->
{{mul 4 5}} <!-- 20 -->
{{div 15 3}} <!-- 5 -->
{{mod 17 5}} <!-- 2 -->
<!-- Placeholder Caddy -->
{{placeholder "http.request.uuid"}} <!-- Request UUID -->
{{env "APP_VERSION"}} <!-- Environment variable -->
Template untuk Sitemap Dinamis #
<!-- sitemap.xml.html (template yang menghasilkan XML) -->
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{{$pages := slice "/" "/about" "/contact" "/blog"}}
{{range $pages}}
<url>
<loc>https://example.com{{.}}</loc>
<lastmod>{{now | date "2006-01-02"}}</lastmod>
<priority>{{if eq . "/"}}1.0{{else}}0.8{{end}}</priority>
</url>
{{end}}
</urlset>
example.com {
root * /var/www/html
templates
# Sajikan sitemap.xml.html sebagai sitemap.xml
@sitemap path /sitemap.xml
handle @sitemap {
rewrite * /sitemap.xml.html
templates
header Content-Type "application/xml; charset=utf-8"
file_server
}
file_server
}
Batasan Templates #
Templates Caddy cocok untuk:
✓ Situs statis dengan sedikit dinamisme
✓ Halaman error kustom
✓ Include komponen reusable (header, footer, nav)
✓ Menampilkan metadata request (IP, path, waktu)
✓ Sitemap dan feed sederhana
Templates Caddy TIDAK cocok untuk:
✗ Aplikasi dengan database
✗ Form processing / POST handling
✗ User authentication
✗ State management
✗ Logika bisnis kompleks
→ Untuk kebutuhan ini, gunakan backend app (Node.js, Go, Python)
dan Caddy sebagai reverse proxy
Template untuk Status Page #
status.example.com {
root * /var/www/status
templates
file_server
}
<!-- /var/www/status/index.html -->
<!DOCTYPE html>
<html>
<head><title>Status Page</title></head>
<body>
<h1>System Status</h1>
<p>Server time: {{now | date "2006-01-02 15:04:05 MST"}}</p>
<p>Your IP: {{.RemoteIP}}</p>
<p>Protocol: {{.Proto}}</p>
{{$uptime := now | date "2006"}}
<p>Running since: {{$uptime}}</p>
<h2>Endpoints</h2>
<table border="1" cellpadding="8">
{{$services := slice "API" "Web" "Database" "Cache"}}
{{range $services}}
<tr>
<td>{{.}}</td>
<td style="color:green">● Operational</td>
</tr>
{{end}}
</table>
</body>
</html>
Ringkasan #
- Direktif
templatesmengaktifkan Go template rendering untuk file HTML yang disajikan olehfile_server— tidak perlu backend untuk konten dinamis sederhana.- Gunakan
{{template "partials/header.html" .}}untuk include komponen reusable — sangat menghemat duplikasi HTML di situs statis.- Halaman error kustom adalah use case terbaik templates — tampilkan pesan yang informatif, link kembali ke beranda, dan info debug saat development.
- Variabel seperti
.RemoteIP,.Host, dan.URItersedia otomatis di semua template tanpa konfigurasi tambahan.- Fungsi
now | date "2006-01-02"menggunakan format Go yang unik (bukan strftime) — nilai referensi Go adalah tanggal01/02 03:04:05PM '06 -0700.- Templates tidak cocok untuk aplikasi dengan database, form processing, atau logika kompleks — gunakan backend application dan Caddy sebagai reverse proxy.
← Sebelumnya: Encode Berikutnya: Map →
Cache dan Templates #
Template rendering terjadi setiap request — pertimbangkan ini saat memilih apakah menggunakan templates atau static files:
example.com {
root * /var/www/html
encode gzip zstd
templates
# CDN bisa meng-cache halaman yang dirender dari template
# karena hasilnya adalah HTML biasa
header Cache-Control "public, max-age=300, s-maxage=3600"
file_server
}
Untuk halaman yang kontennya berubah berdasarkan request (IP client, waktu real-time), pastikan CDN tidak meng-cache dengan nilai no-cache atau private pada header Cache-Control.