Web App Testing – Session – Persiapan

Instalasi Session Package

Seperti yang kita pahami, web server pada dasarnya adalah stateless. Agar kita bisa persist data pengguna, kita perlu gunakan session.

Untuk menggunakan session, kita install package https://github.com/alexedwards/scs.

Buka command prompt lalu jalankan perintah install seperti berikut:

$ go get github.com/alexedwards/scs/v2

Membuat Session

Setelah package selesai diinstall, selanjutnya buat file cmd/web/sessions.go

package main

import (
	"net/http"
	"time"

	"github.com/alexedwards/scs/v2"
)

func getSession() *scs.SessionManager {
	session := scs.New()
	session.Lifetime = 24 * time.Hour
	session.Cookie.Persist = true
	session.Cookie.SameSite = http.SameSiteLaxMode
	session.Cookie.Secure = true

	return session
}

Selanjutnya kita buka cmd/web/main.go, lalu modifikasi seperti berikut

package main

import (
	"log"
	"net/http"

	"github.com/alexedwards/scs/v2"
)

type application struct {
	Session *scs.SessionManager
}

func main() {
	//setup app config
	app := application{}

	//get session manager
	app.Session = getSession()

	//start server
	log.Println("Starting server on port 8080...")
	err := http.ListenAndServe(":8080", app.routes())

	if err != nil {
		log.Fatal(err)
	}

}

Selanjutnya modifikasi file cmd/web/routes.go dengan menambahkan middleware yang disediakan oleh package session yang telah kita install diatas.

package main

import (
	"net/http"

	"github.com/go-chi/chi/v5"
	"github.com/go-chi/chi/v5/middleware"
)

func (app *application) routes() http.Handler {
	mux := chi.NewRouter()

	//register middleware
	mux.Use(middleware.Recoverer)
	mux.Use(app.addIPToContext)
	mux.Use(app.Session.LoadAndSave) //middleware yang disediakan dari session manager

	//register routes
	mux.Get("/", app.Home)
	mux.Post("/login", app.Login)

	//static assets

	fileServer := http.FileServer(http.Dir("./static"))
	mux.Handle("/static/*", http.StripPrefix("/static/", fileServer))

	return mux
}

Menggunakan Session

Untuk menggunakan session, kita buka file cmd/web/handlers.go, lalu tambahkan penggunaan session pada func Home.

package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"path"
	"time"
)

var templatePath = "./templates/"

func (app *application) Home(w http.ResponseWriter, r *http.Request) {
	var td = make(map[string]any)

	if app.Session.Exists(r.Context(), "test") {
		msg := app.Session.GetString(r.Context(), "test")
		td["test"] = msg
	} else {
		app.Session.Put(r.Context(), "test", "Page visit at "+time.Now().UTC().String())
	}
	_ = app.render(w, r, "home.page.gohtml", &TemplateData{Data: td})
}

type TemplateData struct {
	IP   string
	Data map[string]any
}

func (app *application) render(w http.ResponseWriter, r *http.Request, t string, data *TemplateData) error {
	//parse template
	parsedTemplate, err := template.ParseFiles(path.Join(templatePath, t), path.Join(templatePath, "base.layout.gohtml"))
	if err != nil {
		http.Error(w, "bad request", http.StatusBadRequest)
		return err
	}

	//gunakan middleware yang telah kita buat.
	data.IP = app.ipFromContext(r.Context())

	//execute template
	err = parsedTemplate.Execute(w, data)
	if err != nil {
		return err
	}
	return nil
}

func (app *application) Login(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()

	if err != nil {
		log.Println(err)
		http.Error(w, "bad request", http.StatusBadRequest)
		return
	}

	//validation goes here
	form := NewForm(r.PostForm)
	form.Required("email", "password")

	if !form.Valid() {
		fmt.Fprint(w, "Invalid form")
		return
	}

	email := r.Form.Get("email")
	password := r.Form.Get("password")

	log.Println(email, password)

	fmt.Fprint(w, email)
}

Kemudian modifikasi file templates/home.page.gohtml, untuk menampilkan data session.

{{template "base" .}}

{{define "content"}}
    <div class="container">
        <div class="row">
            <div class="col">
                <h1 class="mt-3">Home Page</h1>
                <hr>
                <form action="/login" method="post">
                <div class="mb-3">
                    <label for="email" class="form-label">Email address</label>
                    <input type="email" class="form-control" id="email" name="email">
                </div>
                <div class="mb-3">
                    <label for="password" class="form-label">Password</label>
                    <input type="password" class="form-control" id="password" name="password">
                </div>
                <button type="submit" class="btn btn-primary">Submit</button>
                </form>                
                <hr>
                <small>Your request came from {{.IP}}</small><br/>
                <small>Session: {{index .Data "test"}}</small>
            </div>
        </div>
    </div>
{{end}}

Jika kita jalankan aplikasi dan buka web browser, pada load pertama session masih kosong, jika kita reload, maka data session sudah terisi

Sampai disini kita sudah berhasil setup session pada web app. Jika test dijalankan, akan terjadi error.

Pada modul selanjutnya kita akan lakukan perbaikan fungsi test yang menjadi error setelah ditambahkan session.

Sharing is caring:

Leave a Comment