07 Memahami Cookie
Pengenalan Cookie
Sebelum ke pembahasan Cookie kita perlu ketahui bahwa HTTP merupakan stateless antara client dan server yang artinya server tidak menyimpan data apapun untuk mengingat setiap request dari client. Hal ini bertujuan agar mudah melakukan scalability dari server itu sendiri. Lalu bagaimana cara agar server bisa mengingat sebuah client? misalnya ketika kita sudah login di suatu website, secara otomatis server harus tahu jika client tersebut sudah login sehingga request selanjutnya tidak perlu lagi melakukan login. Hal seperti ini bisanya kita bisa memanfaatkan Cookie.
Cookie adalah fitur HTTP yang mana diberikan oleh server melalui response cookie (key-value) dan client akan menyimpan cookie tersebut di web browser. Dengan demikian, ketika client melakukan request selanjutnya, client akan selalu membawa cookie tersebut secara otomatis. Dan server secara otomatis akan selalu menerima data cookie tersebut yang dibawa oleh client setiap client melakukan request.
Pada Golang, kita bisa menggunakan function http.SetCookie untuk menggunakan cookie di server sehingga nanti dari client bisa secara otomatis menggunakan cookie pada request-nya.
Implementasi
Sekarang kita akan coba memahami lebih dalam dengan memberikan contoh seperti kode dibawah ini.
1func SetCookieHandler(w http.ResponseWriter, r *http.Request) {
2 cookie := new(http.Cookie)
3 cookie.Name = "X-PXN-Name"
4 cookie.Value = r.URL.Query().Get("name")
5 cookie.Path = "/"
6 http.SetCookie(w, cookie)
7 fmt.Fprintf(w, "Success create cookie")
8}
9
10func GetCookieHandler(w http.ResponseWriter, r *http.Request) {
11 cookie, err := r.Cookie("X-PXN-Name")
12 if err != nil {
13 fmt.Fprint(w, "no cookie")
14 } else {
15 fmt.Fprintf(w, "hello %s", cookie.Value)
16 }
17}main.go seperti dibawah ini. 1func main() {
2 mux := http.NewServeMux()
3
4 mux.HandleFunc("/set-cookie", SetCookieHandler)
5 mux.HandleFunc("/get-cookie", GetCookieHandler)
6
7 server := http.Server{
8 Addr: "localhost:8080",
9 Handler: mux,
10 }
11
12 err := server.ListenAndServe()
13 if err != nil {
14 panic(err)
15 }
16}1go build && ./learn-golang-webLalu kita buka browser Chrome atau Mozilla dan lakukan inspect element. Jika sudah diakses menggunakan browser maka akan terlihat seperti gambar dibawah ini.

Lalu ketika kita mengakses handler satu lagi untuk mendapatkan cookie pada url http://localhost:8080/get-cookie, maka akan terlihat seperti gambar dibawah ini.

Kita uji fungsi diatas yang mana akan melakukan set cookie pada endpoint handler tersebut sehingga kita tahu bahwa cookie yang diset itu seperti yang sudah diset pada fungsi tersebut.
1func TestSetCookieHandler(t *testing.T) {
2 type args struct {
3 name string
4 }
5 tests := []struct {
6 name string
7 args args
8 want string
9 }{
10 {
11 name: "set cookie",
12 args: args{
13 name: "santekno",
14 },
15 want: "santekno",
16 },
17 }
18 for _, tt := range tests {
19 t.Run(tt.name, func(t *testing.T) {
20 request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost/say?name=%s", tt.args.name), nil)
21 recorder := httptest.NewRecorder()
22 SetCookieHandler(recorder, request)
23
24 cookies := recorder.Result().Cookies()
25
26 for _, cookie := range cookies {
27 if !reflect.DeepEqual(cookie.Value, tt.want) {
28 t.Errorf("response = %s, want %s", cookie.Value, tt.want)
29 }
30 }
31
32 })
33 }
34}Dan kita juga melakukan unit test untuk fungsi get cookie dibawah ini.
1func TestGetCookieHandler(t *testing.T) {
2 type args struct {
3 name string
4 }
5 tests := []struct {
6 name string
7 args args
8 want string
9 }{
10 {
11 name: "get cookie handler without cookie",
12 args: args{
13 name: "",
14 },
15 want: "no cookie",
16 },
17 {
18 name: "get cookie handler with cookie",
19 args: args{
20 name: "santekno",
21 },
22 want: "hello santekno",
23 },
24 }
25 for _, tt := range tests {
26 t.Run(tt.name, func(t *testing.T) {
27 request := httptest.NewRequest(http.MethodGet, "http://localhost/say", nil)
28 if tt.args.name != "" {
29 cookie := new(http.Cookie)
30 cookie.Name = "X-PXN-Name"
31 cookie.Value = tt.args.name
32 request.AddCookie(cookie)
33 }
34
35 recorder := httptest.NewRecorder()
36 GetCookieHandler(recorder, request)
37
38 response := recorder.Result()
39 body, _ := io.ReadAll(response.Body)
40 bodyString := string(body)
41
42 if !reflect.DeepEqual(bodyString, tt.want) {
43 t.Errorf("response = %s, want %s", bodyString, tt.want)
44 }
45 })
46 }
47}