18 Membuat Middleware Cors Menggunakan Httprouter Pada Golang
Cross-Origin Resource Sharing (CORS) adalah mekanisme keamanan yang memungkinkan atau membatasi permintaan HTTP dari domain yang berbeda. Dalam pengembangan aplikasi web, sering kali ada kebutuhan untuk berinteraksi dengan API yang tidak berasal dari domain yang sama dengan aplikasi. Oleh karena itu, middleware CORS dibutuhkan untuk mengontrol dan memberikan izin akses dari sumber lain untuk memastikan bahwa permintaan dari berbagai origin dapat diterima dan dijawab oleh server dengan aman.
Pada artikel ini, kita akan membahas bagaimana cara membuat middleware CORS di Go menggunakan library httprouter. Artikel ini juga akan mencakup cara membuat unit test untuk middleware ini agar lebih mudah dipahami oleh pemula dalam pengembangan aplikasi web di Go.
Langkah 1: Menyiapkan Proyek Golang
Langkah pertama adalah menyiapkan proyek Golang dan menambahkan dependensi yang diperlukan. Di sini kita akan menggunakan httprouter untuk menangani routing HTTP.
Langkah 1.1: Install Library httprouter
Untuk memulai, pastikan Golang telah terinstall. Kemudian buat folder proyek dan masuk ke folder tersebut:
1mkdir cors-middleware
2cd cors-middlewareBuat file go.mod dengan menjalankan perintah ini:
1go mod init cors-middlewareInstall dependensi httprouter:
1go get github.com/julienschmidt/httprouterSetelah dependensi terinstal, kita bisa mulai membuat kode.
Langkah 1.2: Menyiapkan Routing di Main
Buat file main.go dengan kode berikut:
1package main
2
3import (
4 "log"
5 "net/http"
6 "github.com/julienschmidt/httprouter"
7)
8
9// Define CORS middleware function
10func CORSMiddleware(next httprouter.Handle) httprouter.Handle {
11 return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
12 // Allow all origins, methods, and headers by default
13 w.Header().Set("Access-Control-Allow-Origin", "*")
14 w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
15 w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
16 w.Header().Set("Access-Control-Allow-Credentials", "true")
17
18 // If it's an OPTIONS request, respond with 200 immediately
19 if r.Method == http.MethodOptions {
20 w.WriteHeader(http.StatusOK)
21 return
22 }
23
24 // Call the next handler
25 next(w, r, ps)
26 }
27}
28
29func main() {
30 router := httprouter.New()
31
32 // Apply middleware to a specific route
33 router.GET("/", CORSMiddleware(func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
34 w.Write([]byte("Hello, world!"))
35 }))
36
37 log.Fatal(http.ListenAndServe(":8080", router))
38}Penjelasan:
- Middleware
CORSMiddleware: Fungsi middleware ini menambahkan header CORS pada respons HTTP dan memeriksa metode HTTP OPTIONS untuk mengizinkan preflight request. - Handler Route: Middleware ini diterapkan pada handler GET di root (
/). Jika ada permintaan OPTIONS, server akan mengembalikan status 200. - Running the Server: Pada akhir kode, server akan dijalankan pada port 8080 dengan menggunakan
httprouter.
Langkah 2: Menambahkan Unit Test untuk Middleware CORS
Selanjutnya, kita akan menambahkan unit test untuk memverifikasi bahwa middleware kita bekerja dengan benar. Kita menggunakan library net/http/httptest untuk menguji response dari middleware yang kita buat.
Langkah 2.1: Membuat File Unit Test
Buat file baru dengan nama main_test.go untuk menulis unit test.
1package midleware
2
3import (
4 "net/http"
5 "net/http/httptest"
6 "testing"
7
8 "github.com/julienschmidt/httprouter"
9)
10
11func TestCORS(t *testing.T) {
12 type args struct {
13 method string
14 }
15 tests := []struct {
16 name string
17 args args
18 wantStatusCode int
19 wantNextCalled bool
20 wantCORSHeadersSet bool
21 }{
22 {
23 name: "OPTIONS request should return 200 without calling next",
24 args: args{
25 method: http.MethodOptions,
26 },
27 wantStatusCode: http.StatusOK,
28 wantNextCalled: false,
29 wantCORSHeadersSet: true,
30 },
31 {
32 name: "GET request should call next and return 200",
33 args: args{
34 method: http.MethodGet,
35 },
36 wantStatusCode: http.StatusOK,
37 wantNextCalled: true,
38 wantCORSHeadersSet: true,
39 },
40 {
41 name: "POST request should call next and return 200",
42 args: args{
43 method: http.MethodPost,
44 },
45 wantStatusCode: http.StatusOK,
46 wantNextCalled: true,
47 wantCORSHeadersSet: true,
48 },
49 }
50 for _, tt := range tests {
51 t.Run(tt.name, func(t *testing.T) {
52 recorder := httptest.NewRecorder()
53 request := httptest.NewRequest(tt.args.method, "/", nil)
54 params := httprouter.Params{}
55
56 nextCalled := false
57 next := func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
58 nextCalled = true
59 w.WriteHeader(http.StatusOK)
60 }
61
62 handler := CORS(next)
63 handler(recorder, request, params)
64
65 // Status code
66 if recorder.Code != tt.wantStatusCode {
67 t.Errorf("got status code %v, want %v", recorder.Code, tt.wantStatusCode)
68 }
69
70 // Next handler
71 if nextCalled != tt.wantNextCalled {
72 t.Errorf("next handler call = %v, want %v", nextCalled, tt.wantNextCalled)
73 }
74
75 // CORS headers
76 if tt.wantCORSHeadersSet {
77 headers := recorder.Header()
78 if headers.Get("Access-Control-Allow-Origin") != "*" {
79 t.Error("Access-Control-Allow-Origin header not set to *")
80 }
81 if headers.Get("Access-Control-Allow-Methods") == "" {
82 t.Error("Access-Control-Allow-Methods header missing")
83 }
84 if headers.Get("Access-Control-Allow-Headers") == "" {
85 t.Error("Access-Control-Allow-Headers header missing")
86 }
87 if headers.Get("Access-Control-Allow-Credentials") != "true" {
88 t.Error("Access-Control-Allow-Credentials header not set to true")
89 }
90 }
91 })
92 }
93}Penjelasan:
OPTIONSrequest tidak memanggil handler selanjutnya dan hanya mengembalikan200 OK.GETdanPOSTakan diteruskan ke handler selanjutnya (next) dan juga memeriksa apakah header CORS disetel.- Setiap test juga memverifikasi bahwa header CORS muncul dan sesuai dengan yang diharapkan.
Untuk menjalankan unit test ini, gunakan perintah:
1go testLangkah 3: Menjalankan Aplikasi
Sekarang, Anda bisa menjalankan aplikasi menggunakan perintah:
1go run main.goKunjungi http://localhost:8080 untuk melihat hasil dari aplikasi. Anda akan melihat respons “Hello, world!” dan dapat memverifikasi bahwa CORS bekerja dengan menggunakan alat pengembang di browser untuk memeriksa header.
Kesimpulan
Membangun middleware CORS di Go menggunakan httprouter sangatlah mudah dan memberikan fleksibilitas penuh dalam mengontrol bagaimana aplikasi berinteraksi dengan origin lain. Dengan menggunakan unit test, kita memastikan bahwa middleware yang dibangun berfungsi dengan baik dan sesuai dengan yang diinginkan. Anda bisa menambahkan lebih banyak aturan dan fitur sesuai dengan kebutuhan aplikasi.
Jangan ragu untuk mengeksplorasi dokumentasi lainnya: