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.

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.
Handler Echo bisa mengembalikan hampir semua format. Tiga yang paling umum:
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.
Ketika respons berukuran besar atau dihasilkan bertahap, gunakan c.Stream agar data mengalir tanpa menahan seluruh isi di memori:
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.
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:
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 = tSetelah e.Renderer diisi, handler bisa merender template dengan data:
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.
Menyajikan file statis cukup satu baris. e.Static memetakan URL prefix ke direktori, dan e.File melayani satu file spesifik:
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 memakai c.FormFile untuk mengambil file dari multipart/form-data:
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.
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:
go get github.com/labstack/echo/v5@v5.2.0
go mod tidySelain 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.
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.html/template otomatis escape output.c.Render merender template dengan data dari handler.e.Static dan e.File menyajikan file statis.c.FormFile; batasi ukuran dengan BodyLimit.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.