Best practice with sessions (gorilla/sessions)
Asked Answered
S

1

9

Before starting using sessions in golang I need answers to some questions

session example

import "github.com/gorilla/sessions"

var store = sessions.NewCookieStore([]byte("33446a9dcf9ea060a0a6532b166da32f304af0de"))

func Handler(w http.ResponseWriter, r *http.Request){
    session, _ := store.Get(r, "session-name")
    
    session.Values["foo"] = "bar"
    session.Values[42] = 43
    session.Save(r, w)
    
    fmt.Fprint(w, "Hello world :)")
}

func main(){
    store.Options = &sessions.Options{
        Domain:     "localhost",
        Path:       "/",
        MaxAge:     60 * 15,
        Secure:     false,
        HttpOnly:   true,
    }
}

Q1:

Is it possible to add multiple sessions on the same domain with different names?

session1, _ := store.Get(r, "session-name-1")
session2, _ := store.Get(r, "session-name-2")

When do you need multiple sessions on the same domain?

Q2:

What is the best practice to get the variables from the session? my_session_var = session.Values["foo"]

Q3:

How to check if the session is saved correctly? If you access the same map to both set and get variables?

update

package main

import (
    "github.com/gorilla/sessions"
)

var (
    store = sessions.NewCookieStore([]byte("33446a9dcf9ea060a0a6532b166da32f304af0de"))
)

type handler func(w http.ResponseWriter, r *http.Request, s *sessions.Session)

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request){
    session, _ := store.Get(r, "session-name")
    
    h(w, r, session)
}

func Handler_404(w http.ResponseWriter, r *http.Request, s *sessions.Session){
    fmt.Fprint(w, "Oops, something went wrong!")
}

error

# command-line-arguments
.\mux.go:101: cannot convert Handler_404 (type func(http.ResponseWriter, *http.Request, *sessions.Session)) to type http.HandlerFunc
Spaetzle answered 29/9, 2014 at 18:23 Comment(0)
L
5

The article "BASIC EXTENSION OF GO’S HTTP HANDLERS" (Simon Whitehead) shows an example of where and when to define session.
Instead of doing it in the Handler itself, and having to duplicate a lot of code when you define other Handlers.

With a named type, you can define the Handler you need:

type handler func(w http.ResponseWriter, r *http.Request, db *mgo.Database)

(in your case, it would be a gorilla sessions instead of a mgo session or database)

The init() function can take care of the session creation (here mgo session, but the idea is the same for other framework sessions)

func init() {
    session, err = mgo.Dial("localhost")

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

And you can make sure this function type ('handler') does respect the ServeHTTP() function, taking care of:

  • the session management (clone/close)
  • calling your actual handler (which can have more parameters than just w and r)

    func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        s := session.Clone()
        defer s.Close()
    
        h(w, r, s.DB("example"))
    }
    

Then you can define your actual Handler (again, with more than w and r):

func myHandler(w http.ResponseWriter, r *http.Request, db *mgo.Database) {
    var users []user

    db.C("users").Find(nil).All(&users)

    for _, user := range users {
        fmt.Fprintf(w, "%s is %d years old", user.Name, user.Age)
    }
}

And you can use that handler in your server:

func main() {
    mux := http.NewServeMux()
    mux.Handle("/", handler(myHandler))
    http.ListenAndServe(":8080", mux)
}

The idea is to limit the "plumbing" in main() to a minimum, while having an Handler with more parameters (including your session).
That allows you to use different Handlers with very little plumbing, keeping main() only for the declaration of the different path (and not for the initialization of session and handlers)


Update 2019: in another related context, see also "How to handle sessions".

Leavening answered 29/9, 2014 at 18:43 Comment(2)
have updated my question.. get an error when compilingSpaetzle
@Spaetzle that would be best as a separate question.Leavening

© 2022 - 2024 — McMap. All rights reserved.