Belajar Echo - Response, Rendering & Static Files
Episode 7 of 23

Belajar Echo - Response, Rendering & Static Files

Episode ini membedah pengiriman respons di Echo: JSON, XML, dan HTML, integrasi template engine dengan renderer custom, streaming respons, penyajian file statis, upload file, serta perbaikan keamanan StaticDirectoryHandler pada CVE-2026-55677.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Response adalah wajah API kalian. Sejauh ini kita baru mengirim teks dan JSON sederhana; episode ini memperluas cakupan ke XML, HTML dengan template, streaming, serta penyajian file statis dan upload — kebutuhan nyata hampir semua aplikasi web.

Episode 7 ini membedah pengiriman respons di Echo: JSON, XML, dan HTML; integrasi template engine lewat e.Renderer; streaming respons; e.Static dan e.File; upload file; serta langkah keamanan StaticDirectoryHandler terkait CVE-2026-55677.

Mengirim Berbagai Format Respons

JSON, XML, dan HTML

Handler Echo bisa mengembalikan hampir semua format. Tiga yang paling umum:

Beragam format respons
type Product struct {
	ID    int    `json:"id" xml:"id"`
	Name  string `json:"name" xml:"name"`
	Price int    `json:"price" xml:"price"`
}
 
e.GET("/product/json", func(c echo.Context) error {
	return c.JSON(http.StatusOK, Product{ID: 1, Name: "Keyboard", Price: 500000})
})
 
e.GET("/product/xml", func(c echo.Context) error {
	return c.XML(http.StatusOK, Product{ID: 1, Name: "Keyboard", Price: 500000})
})
 
e.GET("/page", func(c echo.Context) error {
	return c.HTML(http.StatusOK, "<h1>Halo dari Echo</h1>")
})

c.JSON, c.XML, dan c.HTML mengatur Content-Type sekaligus menulis body. Untuk kontrol lebih halus, c.Blob mengirim byte mentah dengan tipe tertentu, dan c.HTMLBlob mengirim HTML dari byte.

Streaming Respons

Ketika respons berukuran besar atau dihasilkan bertahap, gunakan c.Stream agar data mengalir tanpa menahan seluruh isi di memori:

Streaming respons
e.GET("/download", func(c echo.Context) error {
	content := []byte("data bervolume besar yang dikirim bertahap")
	return c.Stream(http.StatusOK, echo.MIMEOctetStream, bytes.NewReader(content))
})

c.Stream memakai io.Reader sebagai sumber, sehingga file besar bisa dialirkan dari disk tanpa dibaca penuh dulu.

Template Rendering dengan Renderer Custom

Mengimplementasikan echo.Renderer

Echo tidak mengikat kalian ke template engine tertentu. Implementasikan antarmuka echo.Renderer dan gunakan library favorit — html/template standar adalah pilihan paling aman karena otomatis escape HTML:

Renderer dengan html/template
type Template struct {
	templates *template.Template
}
 
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}
 
t := &Template{
	templates: template.Must(template.ParseGlob("views/*.html")),
}
e.Renderer = t

Setelah e.Renderer diisi, handler bisa merender template dengan data:

Merender template di handler
e.GET("/welcome", func(c echo.Context) error {
	return c.Render(http.StatusOK, "welcome.html", map[string]string{
		"Name": "Arman",
	})
})

c.Render(http.StatusOK, name, data) menerima status, nama template, dan data. Template engine apa pun — dari html/template, pongo2, hingga amber — bisa dipakai selama mengimplementasikan Render.

File Statis dan Upload

e.Static dan e.File

Menyajikan file statis cukup satu baris. e.Static memetakan URL prefix ke direktori, dan e.File melayani satu file spesifik:

Menyajikan file statis
e.Static("/static", "public")
e.File("/favicon.ico", "public/favicon.ico")

Dengan e.Static("/static", "public"), file public/logo.png bisa diakses di /static/logo.png.

Upload File di Handler

Upload file memakai c.FormFile untuk mengambil file dari multipart/form-data:

Handler upload file
e.POST("/upload", func(c echo.Context) error {
	file, err := c.FormFile("file")
	if err != nil {
		return err
	}
	src, err := file.Open()
	if err != nil {
		return err
	}
	defer src.Close()
	dst, err := os.Create("/tmp/" + file.Filename)
	if err != nil {
		return err
	}
	defer dst.Close()
	if _, err := io.Copy(dst, src); err != nil {
		return err
	}
	return c.JSON(http.StatusOK, map[string]string{"file": file.Filename})
})

Ingat selalu membatasi ukuran upload dengan BodyLimit (episode 6) dan memvalidasi tipe file sebelum menyimpannya.

Keamanan StaticDirectoryHandler

CVE-2026-55677 dan Perbaikannya

Pada 2026 ditemukan CVE-2026-55677, celah yang memungkinkan route bypass pada penanganan direktori statis. Kombinasi pola route dan penanganan ../ pada path bisa mengarahkan request ke file di luar direktori yang diizinkan.

Perbaikan dirilis di Echo 5.2.0 dan 4.15.3. Langkah yang harus kalian ambil:

Perbarui Echo ke versi aman
go get github.com/labstack/echo/v5@v5.2.0
go mod tidy

Selain update, pastikan direktori statis tidak pernah berisi file sensitif seperti .env atau kunci privat. Validasi nama file upload dan hindari meneruskan nilai path langsung dari user tanpa normalisasi.

Penutup

Episode 7 memperluas kemampuan respons kalian: JSON, XML, dan HTML; rendering template dengan renderer custom berbasis html/template; streaming untuk data besar; penyajian file statis dengan e.Static dan e.File; upload file yang aman; serta mitigasi CVE-2026-55677 dengan memperbarui Echo.

Inti yang harus dibawa pulang:

  • c.JSON, c.XML, c.HTML, dan c.Blob menangani format umum.
  • c.Stream mengalirkan data lewat io.Reader tanpa menahan memori.
  • Renderer bersifat pluggable; html/template otomatis escape output.
  • c.Render merender template dengan data dari handler.
  • e.Static dan e.File menyajikan file statis.
  • Upload memakai c.FormFile; batasi ukuran dengan BodyLimit.
  • Update ke Echo 5.2.0 atau 4.15.3 untuk menutup CVE-2026-55677.

Di episode 8 selanjutnya kita akan membahas struktur proyek & clean architecture — organisasi handler, service, dan repository, layout internal/, dependency injection sederhana, serta modularisasi setup router dan middleware agar kode mudah diuji dan diskalakan.