|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- package handlers
-
- import (
- "fmt"
- "io/ioutil"
- "net/http"
- "net/http/cookiejar"
- "net/http/httptest"
- "testing"
- "time"
- )
-
- var (
- store SessionStore
- secret = "butchered at birth"
- )
-
- func TestSession(t *testing.T) {
- stores := map[string]SessionStore{
- "memory": NewMemoryStore(1),
- "redis": NewRedisStore(&RedisStoreOptions{
- Network: "tcp",
- Address: ":6379",
- Database: 1,
- KeyPrefix: "sess",
- }),
- }
- for k, v := range stores {
- t.Logf("testing session with %s store\n", k)
- store = v
- t.Log("SessionExists")
- testSessionExists(t)
- t.Log("SessionPersists")
- testSessionPersists(t)
- t.Log("SessionExpires")
- testSessionExpires(t)
- t.Log("SessionBeforeExpires")
- testSessionBeforeExpires(t)
- t.Log("PanicIfNoSecret")
- testPanicIfNoSecret(t)
- t.Log("InvalidPath")
- testInvalidPath(t)
- t.Log("ValidSubPath")
- testValidSubPath(t)
- t.Log("SecureOverHttp")
- testSecureOverHttp(t)
- }
- }
-
- func setupTest(f func(w http.ResponseWriter, r *http.Request), ckPath string, secure bool, maxAge int) *httptest.Server {
- opts := NewSessionOptions(store, secret)
- if ckPath != "" {
- opts.CookieTemplate.Path = ckPath
- }
- opts.CookieTemplate.Secure = secure
- opts.CookieTemplate.MaxAge = maxAge
- h := SessionHandler(http.HandlerFunc(f), opts)
- return httptest.NewServer(h)
- }
-
- func doRequest(u string, newJar bool) *http.Response {
- var err error
- if newJar {
- http.DefaultClient.Jar, err = cookiejar.New(new(cookiejar.Options))
- if err != nil {
- panic(err)
- }
- }
- res, err := http.Get(u)
- if err != nil {
- panic(err)
- }
- return res
- }
-
- func testSessionExists(t *testing.T) {
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- ssn, ok := GetSession(w)
- if assertTrue(ok, "expected session to be non-nil, got nil", t) {
- ssn.Data["foo"] = "bar"
- assertTrue(ssn.Data["foo"] == "bar", fmt.Sprintf("expected ssn[foo] to be 'bar', got %v", ssn.Data["foo"]), t)
- }
- w.Write([]byte("ok"))
- }, "", false, 0)
- defer s.Close()
-
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
- assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
- }
-
- func testSessionPersists(t *testing.T) {
- cnt := 0
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- ssn, ok := GetSession(w)
- if !ok {
- panic("session not found!")
- }
- if cnt == 0 {
- ssn.Data["foo"] = "bar"
- w.Write([]byte("ok"))
- cnt++
- } else {
- w.Write([]byte(ssn.Data["foo"].(string)))
- }
- }, "", false, 0)
- defer s.Close()
-
- // 1st call, set the session value
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
-
- // 2nd call, get the session value
- res = doRequest(s.URL, false)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("bar"), res, t)
- assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected 2nd response to have 0 cookie, got %d", len(res.Cookies())), t)
- }
-
- func testSessionExpires(t *testing.T) {
- cnt := 0
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- ssn, ok := GetSession(w)
- if !ok {
- panic("session not found!")
- }
- if cnt == 0 {
- w.Write([]byte(ssn.ID()))
- cnt++
- } else {
- w.Write([]byte(ssn.ID()))
- }
- }, "", false, 1) // Expire in 1 second
- defer s.Close()
-
- // 1st call, set the session value
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- id1, err := ioutil.ReadAll(res.Body)
- if err != nil {
- panic(err)
- }
- res.Body.Close()
- time.Sleep(1001 * time.Millisecond)
-
- // 2nd call, get the session value
- res = doRequest(s.URL, false)
- assertStatus(http.StatusOK, res.StatusCode, t)
- id2, err := ioutil.ReadAll(res.Body)
- if err != nil {
- panic(err)
- }
- res.Body.Close()
- sid1, sid2 := string(id1), string(id2)
- assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected 2nd response to have 1 cookie, got %d", len(res.Cookies())), t)
- assertTrue(sid1 != sid2, "expected session IDs to be different, got same", t)
- }
-
- func testSessionBeforeExpires(t *testing.T) {
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- ssn, ok := GetSession(w)
- if !ok {
- panic("session not found!")
- }
- w.Write([]byte(ssn.ID()))
- }, "", false, 1) // Expire in 1 second
- defer s.Close()
-
- // 1st call, set the session value
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- id1, err := ioutil.ReadAll(res.Body)
- if err != nil {
- panic(err)
- }
- res.Body.Close()
- time.Sleep(500 * time.Millisecond)
-
- // 2nd call, get the session value
- res = doRequest(s.URL, false)
- assertStatus(http.StatusOK, res.StatusCode, t)
- id2, err := ioutil.ReadAll(res.Body)
- if err != nil {
- panic(err)
- }
- res.Body.Close()
- sid1, sid2 := string(id1), string(id2)
- assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected 2nd response to have no cookie, got %d", len(res.Cookies())), t)
- assertTrue(sid1 == sid2, "expected session IDs to be the same, got different", t)
- }
-
- func testPanicIfNoSecret(t *testing.T) {
- defer assertPanic(t)
- SessionHandler(http.NotFoundHandler(), NewSessionOptions(nil, ""))
- }
-
- func testInvalidPath(t *testing.T) {
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- _, ok := GetSession(w)
- assertTrue(!ok, "expected session to be nil, got non-nil", t)
- w.Write([]byte("ok"))
- }, "/foo", false, 0)
- defer s.Close()
-
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
- assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected response to have no cookie, got %d", len(res.Cookies())), t)
- }
-
- func testValidSubPath(t *testing.T) {
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- _, ok := GetSession(w)
- assertTrue(ok, "expected session to be non-nil, got nil", t)
- w.Write([]byte("ok"))
- }, "/foo", false, 0)
- defer s.Close()
-
- res := doRequest(s.URL+"/foo/bar", true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
- assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
- }
-
- func testSecureOverHttp(t *testing.T) {
- s := setupTest(func(w http.ResponseWriter, r *http.Request) {
- _, ok := GetSession(w)
- assertTrue(ok, "expected session to be non-nil, got nil", t)
- w.Write([]byte("ok"))
- }, "", true, 0)
- defer s.Close()
-
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
- assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected response to have no cookie, got %d", len(res.Cookies())), t)
- }
-
- // TODO : commented, certificate problem
- func xtestSecureOverHttps(t *testing.T) {
- opts := NewSessionOptions(store, secret)
- opts.CookieTemplate.Secure = true
- h := SessionHandler(http.HandlerFunc(
- func(w http.ResponseWriter, r *http.Request) {
- _, ok := GetSession(w)
- assertTrue(ok, "expected session to be non-nil, got nil", t)
- w.Write([]byte("ok"))
- }), opts)
- s := httptest.NewTLSServer(h)
- defer s.Close()
-
- res := doRequest(s.URL, true)
- assertStatus(http.StatusOK, res.StatusCode, t)
- assertBody([]byte("ok"), res, t)
- assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
- }
|