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.