DEV Community

Mossie Chao
Mossie Chao

Posted on • Updated on

Go fiber with session

ทดลองการใช้งาน Go Fiber กับ middleware ตัวหนึ่งชื่อว่า session


main.go

func main() {
    store := session.New()

    engine := html.New("./views", ".html")
    engine.Reload(true)
    engine.Debug(true)
    engine.Layout("embed")
    engine.Delims("{{", "}}")
    app := fiber.New(fiber.Config{
        Views: engine,
    })

    app.Get("/", func(c *fiber.Ctx) error {
        sess, err := store.Get(c)
        if err != nil {
            log.Println(err)
        }

        log.Println(sess)
        name := sess.Get("name")
        isLogin := name != nil
        UnauthorizedMessage := "You are not login"
        AuthorizedMessage := fmt.Sprintf("Welcome %v", name)

        return c.Render("index", fiber.Map{
            "AuthorizedMessage":   AuthorizedMessage,
            "UnauthorizedMessage": UnauthorizedMessage,
            "IsLogin":             isLogin,
        })
    })

    app.Get("/login", func(c *fiber.Ctx) error {
        sess, err := store.Get(c)
        if err != nil {
            panic(err)
        }

        sess.Set("name", c.Query("name", "unknown user"))
        if err := sess.Save(); err != nil {
            panic(err)
        }

        return c.Redirect("/")
    })

    app.Get("/logout", func(c *fiber.Ctx) error {
        sess, err := store.Get(c)
        if err != nil {
            panic(err)
        }

        sess.Delete("name")

        // Destry session
        if err := sess.Destroy(); err != nil {
            panic(err)
        }

        return c.Redirect("/")
    })

    log.Fatal(app.Listen(":3000"))
}

Enter fullscreen mode Exit fullscreen mode

views/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  {{if .IsLogin}}
    {{.AuthorizedMessage}}
  {{else}}
    {{.UnauthorizedMessage}}
    <form action="/login">
      <label for="fname">Your name</label><br>
      <input type="text" id="name" name="name"><br>
      <input type="submit" value="Login">
    </form> 
  {{end}}
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

ดูจาก log ที่เกิดจากการ request เข้ามา


ทุกครั้งที่ยังไม่ได้ save session รหัสจะเปลี่ยนไปเรื่อย
21:9:12 app         | 2021/02/17 21:09:12 &{5924577f-195a-4342-90c5-33d08322d3ac true 0xc00013cb00 0xc000202150 0xc000262960}
21:9:19 app         | 2021/02/17 21:09:19 &{20b172d6-7836-46e7-9b84-cbd22cea7e28 true 0xc00013cb00 0xc000202150 0xc000262b60}
21:16:58 app         | 2021/02/17 21:16:58 &{4f1bf90a-ca51-4b20-a69f-3263cf41aa17 false 0xc00009e000 0xc000202150 0xc0000e1120}

แต่หลังจากมีการ login ได้มีการ save session แล้ว ตัว session นั้น รหัสจะไม่เปลี่ยน
21:2:36 app         | 2021/02/17 21:02:36 &{4f1bf90a-ca51-4b20-a69f-3263cf41aa17 false 0xc00029e000 0xc000202150 0xc0002900a0}
21:2:36 app         | views: parsed template: index
21:2:50 app         | 2021/02/17 21:02:50 &{4f1bf90a-ca51-4b20-a69f-3263cf41aa17 false 0xc00029e000 0xc000202150 0xc0002903e0}
21:2:50 app         | views: parsed template: index
21:2:55 app         | 2021/02/17 21:02:55 &{4f1bf90a-ca51-4b20-a69f-3263cf41aa17 false 0xc00029e000 0xc000202150 0xc000290620}
Enter fullscreen mode Exit fullscreen mode

แต่ถ้า api เรามีการ compile ใหม่ ทำให้ค่า store เปลี่ยนใหม่ session ทั้งหมดจะถูกทำลายทันที

จริงๆ แล้ว package fiber session มันอำนวยความสำดวกให้เราเฉยๆ โดยการที่

  • สร้าง uuid ขึ้นมาให้เมื่อไม่พบว่า request นั้นมีการแนบ cookie มาให้
  • ใน method save มันก็จะ แนบ uuid เข้าไปใน fiber context cookie ให้ก่อนการส่ง response ออกไป

ปัญหาที่เจอ

  • Cookie แนบมากับหลังบ้าน แต่หน้าบ้านไม่เก็บ cookie เมื่อใช้งาน axios > เราต้องไปตั้งค่า axios 2 อย่าง
axios.defaults.baseURL = `${BASE_URL}`
axios.defaults.withCredentials = true
Enter fullscreen mode Exit fullscreen mode

Oldest comments (2)

Collapse
 
vietlib profile image
vietlib

how can i declare session middleware in app.go and using session middleware in other package (for example: user package) ? thank you

Collapse
 
mossnana profile image
Mossie Chao

In my opinion, use store method func (s *Store) Get(c *fiber.Ctx) (*Session, error)
by pass store into your other package.