Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
03 Oct 2023 · 4 mnt baca ·Artikel 62 / 119
Go

03 Mempelajari Route Pattern

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

Penggunaan Named Parameter

Apakah Router Pattern itu memiliki Pola? Betul sekali setiap endpoint itu memiliki pola parameter pada suatu URL dan sering disebut dengan Named Parameter. Named Parameter ini adalah pola pembuatan parameter dengan menggunakan nama. Setiap nama parameter diawali dengan titik dua : lalu diikuti dengan nama parameter-nya. Misalkan contoh seperti dibawah ini.

Pattern/user/:user
/user/santeknomatch
/user/kamumatch
/user/santekno/profilenot match
/user/not match

Kita akan mencoba mengimplementasikan bagaimana pada Named Parameter ini dibuat pada Golang. Pertama kita perlu buat terlebih dahulu fungsi handler seperti dibawah ini.

go
1func NamedParameterHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
2	text := "Product " + p.ByName("id") + " Item " + p.ByName("itemId")
3	fmt.Fprint(w, text)
4}

Selanjutnya, buat router method GET pada file main.go untuk menginisialisasi endpoint Named Parameter yang kita buat seperti dibawah ini.

go
1router.GET("/product/:id/items/:itemId", NamedParameterHandler)

Lalu jalankan program dan lakukan pengetesan dengan menggunakan curl.

bash
1curl --location --request GET 'localhost:8080/product/1/items/2'

Maka akan muncul hasil seperti dibawah ini.

bash
1➜  santekno-hugo git:(main) curl --location --request GET 'localhost:8080/product/1/items/2'
2Product 1 Item 2% 

Selain testing manual kita pastikan juga membuat unit test dari handler yang sudah kita buat.

go
 1func TestNamedParameterHandler(t *testing.T) {
 2	type args struct {
 3		id     string
 4		itemId string
 5	}
 6	tests := []struct {
 7		name string
 8		args args
 9		want string
10	}{
11		{
12			name: "test get params with product 1",
13			args: args{
14				id:     "1",
15				itemId: "2",
16			},
17			want: "Product 1 Item 2",
18		},
19		{
20			name: "test get params with product 2",
21			args: args{
22				id:     "2",
23				itemId: "3",
24			},
25			want: "Product 2 Item 3",
26		},
27	}
28	for _, tt := range tests {
29		t.Run(tt.name, func(t *testing.T) {
30			request := httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost/product/%s/item/%s", tt.args.id, tt.args.itemId), nil)
31			recorder := httptest.NewRecorder()
32			NamedParameterHandler(recorder, request, httprouter.Params{
33				{
34					Key:   "id",
35					Value: tt.args.id,
36				},
37				{
38					Key:   "itemId",
39					Value: tt.args.itemId,
40				},
41			})
42
43			response := recorder.Result()
44			body, _ := io.ReadAll(response.Body)
45			bodyString := string(body)
46
47			assert.Equal(t, tt.want, bodyString)
48		})
49	}
50}

Penggunaan Catch All Parameters

Selain Named Parameter, route pattern juga ada yang namanya Catch All Parameters yaitu menangkap semua parameter yang mana biasanya diawali dengan bintang *, lalu diikuti dengan nama parameter dan harus berada pada posisi terakhir URL. Lebih jelasnya berikut contoh pattern dibawah ini.

Pattern/src/*filepath
/user/not match
/user/namafilematch
/user/subdirektori/namafilematch

Cara kita mengimplementasikan Catch All Parameters sama halnya dengan Named Parameter tetapi pembedanya yaitu pada tanda, jika Named Parameter menggunakan tanda titik dua : sedangkan pada Catch All Parameters itu menggunakan tanda bintang *.

Baiklah kita coba buat fungsi handler terlebih dahulu.

go
1func CatchAllParameterHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
2	text := "Image " + p.ByName("image")
3	fmt.Fprint(w, text)
4}

Lalu kita tambahkan router dengan method GET

go
1router.GET("/images/*image", CatchAllParameterHandler)

Jalankan program dan kita coba lakukan pengetesan dengan menggunakan curl ini.

bash
1curl --location --request GET 'localhost:8080/images/small/image.jpg'

Setelah dijalankan maka akan terlihat keluaran dan mencetak seperti ini.

bash
1➜  santekno-hugo git:(main) ✗ curl --location --request GET 'localhost:8080/images/small/image.jpg'
2Image /small/image.jpg%

Kita tambahkan juga unit test pada handler yang sudah kita buat agar memastikan kode kita benar-benar sesuai dengan ekspektasi kita.

go
 1func TestCatchAllParameterHandler(t *testing.T) {
 2	type args struct {
 3		image string
 4	}
 5	tests := []struct {
 6		name string
 7		args args
 8		want string
 9	}{
10		{
11			name: "get image",
12			args: args{
13				image: "photo.jpg",
14			},
15			want: "Image photo.jpg",
16		},
17		{
18			name: "get image with path",
19			args: args{
20				image: "small/photo.jpg",
21			},
22			want: "Image small/photo.jpg",
23		},
24	}
25	for _, tt := range tests {
26		t.Run(tt.name, func(t *testing.T) {
27			request := httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost/images/%s", tt.args.image), nil)
28			recorder := httptest.NewRecorder()
29			CatchAllParameterHandler(recorder, request, httprouter.Params{
30				{
31					Key:   "image",
32					Value: tt.args.image,
33				},
34			})
35
36			response := recorder.Result()
37			body, _ := io.ReadAll(response.Body)
38			bodyString := string(body)
39
40			assert.Equal(t, tt.want, bodyString)
41		})
42	}
43}

Artikel Terkait

💬 Komentar