Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cannot get gorilla session value by key

Tags:

go

gorilla

I cannot get value from session this way, it is nil:

session := initSession(r)
valWithOutType := session.Values[key]

Full code:

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "log"
    "net/http"
)

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/setSession", handler1).Methods("GET")
    rtr.HandleFunc("/getSession", handler2).Methods("GET")
    http.Handle("/", rtr)
    log.Println("Listening...")
    http.ListenAndServe(":3000", http.DefaultServeMux)
}

func handler1(w http.ResponseWriter, r *http.Request) {
    SetSessionValue(w, r, "key", "value")
    w.Write([]byte("setSession"))
}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("getSession"))
    value := GetSessionValue(w, r, "key")
    fmt.Println("value from session")
    fmt.Println(value)
}

var authKey = []byte("secret") // Authorization Key

var encKey = []byte("encKey") // Encryption Key

var store = sessions.NewCookieStore(authKey, encKey)

func initSession(r *http.Request) *sessions.Session {
    store.Options = &sessions.Options{
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
    }
    session, err := store.Get(r, "golang_cookie")
    if err != nil {
        panic(err)
    }

    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}

Output:

myMac ~/forStack/session $ go run ./session.go
2015/01/30 16:47:26 Listening...

First I open url http://localhost:3000/setSession and get output:

set session with key key and value value

Then I open url http://localhost:3000/getSession and get output:

valWithOutType: %!s(<nil>)
cannot get session value by key: key
value from session

Why valWithOutType is nil, although I set it requesting /setSession?

Update

I changed code according to @isza answer, but session value is still nil.

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "github.com/gorilla/sessions"
    "log"
    "net/http"
)

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/setSession", handler1).Methods("GET")
    rtr.HandleFunc("/getSession", handler2).Methods("GET")
    http.Handle("/", rtr)
    log.Println("Listening...")
    store.Options = &sessions.Options{
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
        Path:     "/", // to match all requests
    }
    http.ListenAndServe(":3000", http.DefaultServeMux)

}

func handler1(w http.ResponseWriter, r *http.Request) {
    SetSessionValue(w, r, "key", "value")
    w.Write([]byte("setSession"))
}

func handler2(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("getSession"))
    value := GetSessionValue(w, r, "key")
    fmt.Println("value from session")
    fmt.Println(value)
}

var authKey = []byte("secret") // Authorization Key

var encKey = []byte("encKey") // Encryption Key

var store = sessions.NewCookieStore(authKey, encKey)

func initSession(r *http.Request) *sessions.Session {
    session, err := store.Get(r, "golang_cookie")
    if err != nil {
        panic(err)
    }
    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}
like image 352
Maxim Yefremov Avatar asked Jan 30 '15 14:01

Maxim Yefremov


3 Answers

What you are probably doing in your init session function with the get method you are restarting the whole session again so every time you do it the session is empty. I did a quick hack around what you wrote to show you where your error is. Please work around this example!

package appSession

import (        
    "net/http"
    "fmt"
    "log"
    "github.com/gorilla/sessions"    
)

var appSession *sessions.Session;

var authKey = []byte("qwer")
var encKey = []byte("asdf")

var store = sessions.NewCookieStore(authKey, encKey)    

func initSession(r *http.Request) *sessions.Session {

    log.Println("session before get", appSession)

    if appSession != nil {    
        return appSession;    
    }

    session, err := store.Get(r, "golang_cookie")
    appSession = session;

    log.Println("session after get", session)
    if err != nil {
        panic(err)
    }
    return session
}

func SetSessionValue(w http.ResponseWriter, r *http.Request, key, value string) {
    session := initSession(r)
    session.Values[key] = value
    fmt.Printf("set session with key %s and value %s\n", key, value)
    session.Save(r, w)
}

func GetSessionValue(w http.ResponseWriter, r *http.Request, key string) string {   
    session := initSession(r)
    valWithOutType := session.Values[key]
    fmt.Printf("valWithOutType: %s\n", valWithOutType)
    value, ok := valWithOutType.(string)
    log.Println("returned value: ", value);

    if !ok {
        fmt.Println("cannot get session value by key: " + key)
    }
    return value
}
like image 143
Hubert Sobków Avatar answered Nov 11 '22 03:11

Hubert Sobków


In your initSession() function you change the store options:

store.Options = &sessions.Options{
    MaxAge:   3600 * 1, // 1 hour
    HttpOnly: true,
}

The Options struct also contains an important Path field to which the cookie will apply. If you don't set it, its default value will be the empty string: "". This will most likely cause that the cookie will not be matched with any of your urls/paths, so your existing session will not be found.

Add a path to match all your urls like this:

store.Options = &sessions.Options{
    Path:     "/",      // to match all requests
    MaxAge:   3600 * 1, // 1 hour
    HttpOnly: true,
}

Also you shouldn't change store.Options in each call of initSession() since you call this in each incoming request. Just set this once when you create your store like this:

var store = sessions.NewCookieStore(authKey, encKey)

func init() {
    store.Options = &sessions.Options{
        Path:     "/",      // to match all requests
        MaxAge:   3600 * 1, // 1 hour
        HttpOnly: true,
    }
}
like image 23
icza Avatar answered Nov 11 '22 04:11

icza


As I have not found answer I decided not to use cookie store but use redis store for sessions. And I found full working example here

package main

import (
    "fmt"
    "github.com/aaudis/GoRedisSession"
    "log"
    "net/http"
)

var (
    redis_session *rsess.SessionConnect
)

func main() {
    // Configurable parameters
    rsess.Prefix = "sess:" // session prefix (in Redis)
    rsess.Expire = 1800    // 30 minute session expiration

    // Connecting to Redis and creating storage instance
    temp_sess, err := rsess.New("sid", 0, "127.0.0.1", 6379)
    if err != nil {
        log.Printf("%s", err)
    }

    redis_session = temp_sess // assing to global variable

    http.HandleFunc("/", Root)
    http.HandleFunc("/get", Get)
    http.HandleFunc("/set", Set)
    http.HandleFunc("/des", Des)
    http.ListenAndServe(":8888", nil)
}

func Root(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("Content-Type", "text/html")
    fmt.Fprintf(w, `
        Redis session storage example:<br><br>
        <a href="/set">Store key in session</a><br>
        <a href="/get">Get key value from session</a><br>
        <a href="/des">Destroy session</a>
    `)
}

// Destroy session
func Des(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    s.Destroy(w)
    fmt.Fprintf(w, "Session deleted!")
}

// Set variable to session
func Set(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    s.Set("UserID", "1000")
    fmt.Fprintf(w, "Setting session variable done!")
}

// Get variable from session
func Get(w http.ResponseWriter, r *http.Request) {
    s := redis_session.Session(w, r)
    fmt.Fprintf(w, "Value %s", s.Get("UserID"))
}
like image 37
Maxim Yefremov Avatar answered Nov 11 '22 05:11

Maxim Yefremov