Episode ini membedah sistem routing Echo: path parameter dengan titik dua, wildcard, matching berbasis regex, query parameter, route group, serta virtual host untuk melayani banyak domain dalam satu server.

Routing adalah otot utama Echo. Router radix tree yang kita bahas di episode 2 kini akan bekerja dengan berbagai pola rute: parameter, wildcard, regex, query, hingga virtual host. Memahami pola ini dengan benar akan mencegah error route conflict yang sering menjebak developer pemula.
Episode 4 ini membedah sistem routing Echo secara menyeluruh: path parameter dengan tanda titik dua, wildcard, matching berbasis regex, query parameter, route group dengan subrouter, hingga multiple host dengan e.Vhost.
Path parameter memungkinkan satu route melayani banyak nilai. Gunakan tanda titik dua untuk mendefinisikan parameter, lalu ambil nilainya dengan c.Param:
e.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
return c.String(http.StatusOK, "user id: "+id)
})Route /users/:id — dideklarasikan lewat e.GET("/users/:id", handler) — mencocokkan /users/42 dan /users/arman. Nilai setelah /users/ diambil oleh c.Param("id"). Perhatikan bahwa :id tidak mencocokkan slash — parameter hanya mengikat satu segmen path.
Kalian bisa menulis beberapa parameter dalam satu route. Router akan memetakan setiap segmen ke nama yang sesuai:
e.GET("/users/:id/posts/:postId", func(c echo.Context) error {
userID := c.Param("id")
postID := c.Param("postId")
return c.String(http.StatusOK, userID+" "+postID)
})Saat request /users/7/posts/99 masuk, c.Param("id") bernilai 7 dan c.Param("postId") bernilai 99. Nama parameter bebas, selama konsisten antara deklarasi route dan pengambilan.
Kadang kalian perlu mencocokkan sisa path yang panjangnya tidak pasti. Wildcard /* menangkap semua segmen setelahnya, termasuk slash:
e.GET("/files/*", func(c echo.Context) error {
path := c.Param("*")
return c.String(http.StatusOK, "file path: "+path)
})Wildcard /* bersifat catch-all: route /files/* mencocokkan /files/a, /files/a/b, dan seterusnya. c.Param("*") mengembalikan bagian path setelah /files/.
Untuk kontrol yang lebih ketat, Echo mendukung batasan regex pada parameter. Pola :id\\d+ hanya mencocokkan satu atau lebih digit:
e.GET("/users/:id\\d+", func(c echo.Context) error {
return c.String(http.StatusOK, "numeric id: "+c.Param("id"))
})Route ini hanya menerima id numerik; request seperti /users/abc tidak cocok dan akan jatuh ke route lain atau menghasilkan 404. Regex memakai sintaks Go standar, jadi pola apa pun yang valid di regexp bisa dipakai.
Selain path, informasi bisa datang lewat query string. c.QueryParam mengambil satu nilai, sedangkan c.QueryParams mengembalikan seluruh pasangan key-value:
e.GET("/search", func(c echo.Context) error {
query := c.QueryParam("q")
page := c.QueryParam("page")
return c.JSON(http.StatusOK, map[string]string{
"query": query,
"page": page,
})
})Request GET /search?q=echo&page=2 akan menghasilkan respons dengan nilai q dan page. Perhatikan bahwa query parameter selalu opsional — jika tidak dikirim, nilainya adalah string kosong.
curl "http://localhost:8080/search?q=echo&page=2"Route group menyatukan rute dengan prefix dan middleware yang sama. Ini pola standar untuk versi API atau modul tertentu:
api := e.Group("/api/v1")
api.Use(middleware.CORS())
api.GET("/users", listUsers)
api.POST("/users", createUser)Semua route di group otomatis memiliki prefix /api/v1 dan menjalankan middleware CORS. Untuk rute yang tidak cocok dengan pola apa pun, e.Any mendaftarkan handler di semua metode HTTP:
e.Any("/webhook", handleWebhook)Ketika satu server harus melayani banyak domain, Echo menyediakan e.Vhost. Setiap vhost berisi echo.Echo tersendiri dengan router dan middleware sendiri:
a := e.Vhost("api.example.com")
a.GET("/", handleAPI)
b := e.Vhost("www.example.com")
b.Use(middleware.Gzip())
b.GET("/", handleWeb)Request dengan header Host: api.example.com diarahkan ke vhost a, sedangkan www.example.com ditangani vhost b. Ini berguna untuk arsitektur monolith yang melayani banyak domain dalam satu proses.
Konflik terjadi ketika dua route memiliki pola dan prioritas yang sama. Contoh klasik: /users/:id dan /users/:name — keduanya mencocokkan format yang sama sehingga Echo menolak pendaftaran kedua.
e.Debug = true
go run .Set e.Debug = true lalu jalankan server, dan setiap request akan mencetak informasi debugging. Gunakan juga e.Routes() untuk mencetak seluruh route yang terdaftar saat proses boot. Teknik ini akan kalian pakai lagi saat troubleshooting di episode 19.
Episode 4 membuat kalian menguasai sistem routing Echo: path parameter dengan :id, wildcard /* untuk sisa path, regex :id\\d+ untuk batasan ketat, query parameter, route group dengan subrouter, dan virtual host untuk banyak domain dalam satu server.
Inti yang harus dibawa pulang:
:id mencocokkan satu segmen path, diambil lewat c.Param./* mencocokkan seluruh sisa path.:id\\d+ membatasi nilai parameter.c.QueryParam dan c.QueryParams membaca query string.e.Group membungkus rute dengan prefix dan middleware bersama.e.Any mendaftarkan handler untuk semua metode HTTP.e.Vhost melayani banyak domain dengan router terpisah.Di episode 5 selanjutnya kita akan membahas binding & validation — mengubah JSON, XML, atau form menjadi struct dengan c.Bind, tag struct untuk query dan URI binding, binder custom, validator pluggable go-playground, dan penanganan error 400 secara terpusat.