Belajar Chi - Konsep Dasar & Arsitektur Utama
Episode 2 of 23

Belajar Chi - Konsep Dasar & Arsitektur Utama

Episode ini membedah arsitektur chi dari dalam: chi.NewRouter yang mengembalikan http.Handler, radix tree untuk mencocokkan pola, serta chi.RouteContext yang membawa params dan middleware stack lewat context Go. Kalian juga mengenal komponen utama router dan package middleware bawaan.

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

Pendahuluan

Episode 1 menjelaskan mengapa chi ada. Episode 2 membuka kap mesin: bagaimana chi bekerja di balik layar. Memahami arsitektur internal ini penting, karena banyak kesalahan penggunaan chi — misalnya kehilangan params atau middleware yang tidak berjalan — berakar pada kurang pahamnya konsep chi.RouteContext dan alur context.

Target episode ini sederhana: setelah selesai, kalian bisa menjelaskan alur sebuah request dari masuk sampai handler tereksekusi, termasuk dari mana params diambil dan mengapa urutan middleware penting.

Router adalah http.Handler

chi.NewRouter

chi.NewRouter() mengembalikan nilai bertipe chi.Router — sebuah interface yang implementasinya juga merupakan http.Handler. Itulah sebabnya router chi bisa langsung diserahkan ke http.ListenAndServe tanpa adaptor:

Router adalah http.Handler
package main
 
import (
    "net/http"
 
    "github.com/go-chi/chi/v5"
)
 
func main() {
    r := chi.NewRouter()
    r.Get("/", func(w http.ResponseWriter, req *http.Request) {
        w.Write([]byte("halo dari chi"))
    })
    http.ListenAndServe(":8080", r)
}

Perhatikan tidak ada magic di sini. http.ListenAndServe(":8080", r) menerima router karena router mengimplementasikan ServeHTTP — persis seperti handler biasa.

ServeHTTP sebagai Pintu Masuk

Saat request datang, method ServeHTTP pada router dijalankan. Router membaca method dan path, lalu mencocokkan dengan pola yang sudah didaftarkan. Proses pencocokan inilah yang dioptimalkan lewat struktur khusus bernama radix tree.

Radix Tree dan Pencocokan Pola

Matching yang Cepat

Router internal chi menyusun seluruh pola rute dalam radix tree — sebuah pohon di mana setiap level merepresentasikan segmen path. Menemukan handler untuk /users/42 cukup dengan menelusuri node users lalu node {id}, tanpa harus membandingkan satu per satu seluruh pola yang terdaftar.

Keuntungan radix tree:

  • Efisien: kompleksitas pencarian sebanding dengan panjang path, bukan jumlah route.
  • Terstruktur: pola dengan prefix sama berbagi node, sehingga deklarasi rute rapi.
  • Deterministik: urutan matching konsisten, mudah diprediksi.

Params Menempel pada Node

Setiap node yang menyimpan pola param (misalnya {id}) mencatat nama dan nilai saat request dicocokkan. Nilai-nilai ini disimpan di dalam route context yang akan kita bahas berikutnya.

Akses RouteContext
rctx := chi.RouteContext(req.Context())
param := rctx.URLParam("id")

chi.RouteContext(req.Context()) mengambil struktur konteks rute dari context request, lalu rctx.URLParam("id") membaca nilai param yang dicocokkan. Ini jalur yang dipakai chi.URLParam di episode 4.

RouteContext dan Context

Go Context sebagai Pembawa

Sejak Go 1.7, package context menjadi bagian standard library dan http.Request membawa context. chi memanfaatkannya dengan menyisipkan route context ke dalam context request. Dengan begitu, params dan middleware stack berpindah dari router ke handler tanpa variabel global.

Komponen penting dalam route context:

  • URLParams: map nilai param hasil matching.
  • RoutePath: path yang sedang dicocokkan.
  • RoutePattern: pola rute final yang terpilih.
  • Middleware stack: daftar middleware yang menunggu dijalankan.

Middleware Stack

Saat request lewat, middleware yang terdaftar dijalankan berurutan seperti onion. Setiap middleware menerima http.Handler dan mengembalikan http.Handler baru. Route context menyimpan sisa middleware yang belum dipanggil sehingga subrouter dan With bisa menambahkan lapisan baru secara dinamis.

Komponen Utama chi

  • Router / Mux: chi.NewRouter() — pengelola pola rute dan handler.
  • RouteContext: pembawa params dan middleware stack di dalam context.
  • URLParam: API membaca nilai param (chi.URLParam).
  • Middlewares: slice middleware pada level router, diakses lewat r.Middlewares().
  • Chain: middleware.Chain — merangkai middleware eksplisit menjadi satu handler.
  • Mount: r.Mount — memasang sub-app sebagai handler pada prefix path.

Seluruh komponen itu bekerja di atas satu basis: net/http.

Package middleware Bawaan

chi menyertakan middleware package berisi utilitas siap pakai. Beberapa yang akan sering kalian pakai:

  • middleware.RequestID dan middleware.RealIP untuk metadata request.
  • middleware.Logger untuk logging sederhana.
  • middleware.Recoverer untuk menangkap panic.
  • middleware.Timeout dan middleware.Throttle untuk pengendalian.
  • middleware.Compress, middleware.BasicAuth, dan middleware.RedirectSlashes.

Kita akan mengeksplorasi semuanya secara mendalam mulai episode 6. Untuk sekarang, cukup pahami bahwa package ini hanyalah fungsi func(http.Handler) http.Handler biasa.

Lihat dokumentasi middleware
go doc github.com/go-chi/chi/v5/middleware

go doc github.com/go-chi/chi/v5/middleware menampilkan daftar lengkap middleware yang tersedia beserta tanda tangannya.

Penutup

Inti yang harus dibawa pulang:

  • chi.NewRouter() mengembalikan chi.Router yang juga http.Handler.
  • Pola rute disusun dalam radix tree untuk matching yang cepat.
  • chi.RouteContext dibawa lewat context Go dan menyimpan params serta middleware stack.
  • Params diambil lewat chi.URLParam atau rctx.URLParam.
  • Middleware bawaan hanyalah fungsi func(http.Handler) http.Handler.
  • Tidak ada re-invention: semuanya di atas net/http.

Di episode 3 selanjutnya kita akan menulis kode pertama yang benar-benar jalan: setup dan hello world — dari install chi v5, chi.NewRouter(), handler pertama, sampai prinsip chi adalah net/http yang bisa kalian raba langsung lewat curl.