2017-08-31 17:20:58 +02:00
|
|
|
package scs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-04-28 07:30:35 +02:00
|
|
|
"io/ioutil"
|
2017-08-31 17:20:58 +02:00
|
|
|
"net/http"
|
2019-04-28 07:30:35 +02:00
|
|
|
"net/http/cookiejar"
|
|
|
|
"net/http/httptest"
|
2017-08-31 17:20:58 +02:00
|
|
|
"strings"
|
|
|
|
"testing"
|
2019-04-28 07:30:35 +02:00
|
|
|
"time"
|
2017-08-31 17:20:58 +02:00
|
|
|
)
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
type testServer struct {
|
|
|
|
*httptest.Server
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func newTestServer(t *testing.T, h http.Handler) *testServer {
|
|
|
|
ts := httptest.NewTLSServer(h)
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
jar, err := cookiejar.New(nil)
|
2017-08-31 17:20:58 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2019-04-28 07:30:35 +02:00
|
|
|
ts.Client().Jar = jar
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
ts.Client().CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
|
|
return http.ErrUseLastResponse
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
return &testServer{ts}
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func (ts *testServer) execute(t *testing.T, urlPath string) (http.Header, string) {
|
|
|
|
rs, err := ts.Client().Get(ts.URL + urlPath)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
defer rs.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(rs.Body)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
return rs.Header, string(body)
|
|
|
|
}
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func extractTokenFromCookie(c string) string {
|
|
|
|
parts := strings.Split(c, ";")
|
|
|
|
return strings.SplitN(parts[0], "=", 2)[1]
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func TestEnable(t *testing.T) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager := New()
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/put", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager.Put(r.Context(), "foo", "bar")
|
2019-04-28 07:30:35 +02:00
|
|
|
}))
|
|
|
|
mux.HandleFunc("/get", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
s := sessionManager.Get(r.Context(), "foo").(string)
|
2019-04-28 07:30:35 +02:00
|
|
|
w.Write([]byte(s))
|
|
|
|
}))
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-06-18 12:49:37 +02:00
|
|
|
ts := newTestServer(t, sessionManager.LoadAndSave(mux))
|
2019-04-28 07:30:35 +02:00
|
|
|
defer ts.Close()
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
header, _ := ts.execute(t, "/put")
|
|
|
|
token1 := extractTokenFromCookie(header.Get("Set-Cookie"))
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
header, body := ts.execute(t, "/get")
|
|
|
|
if body != "bar" {
|
|
|
|
t.Errorf("want %q; got %q", "bar", body)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
2019-04-28 07:30:35 +02:00
|
|
|
if header.Get("Set-Cookie") != "" {
|
|
|
|
t.Errorf("want %q; got %q", "", header.Get("Set-Cookie"))
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
header, _ = ts.execute(t, "/put")
|
|
|
|
token2 := extractTokenFromCookie(header.Get("Set-Cookie"))
|
|
|
|
if token1 != token2 {
|
|
|
|
t.Error("want tokens to be the same")
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func TestLifetime(t *testing.T) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager := New()
|
|
|
|
sessionManager.Lifetime = 500 * time.Millisecond
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/put", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager.Put(r.Context(), "foo", "bar")
|
2019-04-28 07:30:35 +02:00
|
|
|
}))
|
|
|
|
mux.HandleFunc("/get", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
v := sessionManager.Get(r.Context(), "foo")
|
2019-04-28 07:30:35 +02:00
|
|
|
if v == nil {
|
|
|
|
http.Error(w, "foo does not exist in session", 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write([]byte(v.(string)))
|
|
|
|
}))
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-06-18 12:49:37 +02:00
|
|
|
ts := newTestServer(t, sessionManager.LoadAndSave(mux))
|
2019-04-28 07:30:35 +02:00
|
|
|
defer ts.Close()
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
ts.execute(t, "/put")
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
_, body := ts.execute(t, "/get")
|
|
|
|
if body != "bar" {
|
|
|
|
t.Errorf("want %q; got %q", "bar", body)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
2019-04-28 07:30:35 +02:00
|
|
|
time.Sleep(time.Second)
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
_, body = ts.execute(t, "/get")
|
|
|
|
if body != "foo does not exist in session\n" {
|
|
|
|
t.Errorf("want %q; got %q", "foo does not exist in session\n", body)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func TestIdleTimeout(t *testing.T) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager := New()
|
|
|
|
sessionManager.IdleTimeout = 200 * time.Millisecond
|
|
|
|
sessionManager.Lifetime = time.Second
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/put", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager.Put(r.Context(), "foo", "bar")
|
2019-04-28 07:30:35 +02:00
|
|
|
}))
|
|
|
|
mux.HandleFunc("/get", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
v := sessionManager.Get(r.Context(), "foo")
|
2019-04-28 07:30:35 +02:00
|
|
|
if v == nil {
|
|
|
|
http.Error(w, "foo does not exist in session", 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write([]byte(v.(string)))
|
|
|
|
}))
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-06-18 12:49:37 +02:00
|
|
|
ts := newTestServer(t, sessionManager.LoadAndSave(mux))
|
2019-04-28 07:30:35 +02:00
|
|
|
defer ts.Close()
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
ts.execute(t, "/put")
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
ts.execute(t, "/get")
|
2017-08-31 17:20:58 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
time.Sleep(150 * time.Millisecond)
|
|
|
|
_, body := ts.execute(t, "/get")
|
|
|
|
if body != "bar" {
|
|
|
|
t.Errorf("want %q; got %q", "bar", body)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
_, body = ts.execute(t, "/get")
|
|
|
|
if body != "foo does not exist in session\n" {
|
|
|
|
t.Errorf("want %q; got %q", "foo does not exist in session\n", body)
|
2017-08-31 17:20:58 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-07 19:03:35 +02:00
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
func TestDestroy(t *testing.T) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager := New()
|
2019-04-28 07:30:35 +02:00
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/put", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
sessionManager.Put(r.Context(), "foo", "bar")
|
2019-04-28 07:30:35 +02:00
|
|
|
}))
|
|
|
|
mux.HandleFunc("/destroy", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
err := sessionManager.Destroy(r.Context())
|
2019-04-28 07:30:35 +02:00
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
mux.HandleFunc("/get", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
2019-06-18 12:49:37 +02:00
|
|
|
v := sessionManager.Get(r.Context(), "foo")
|
2019-04-28 07:30:35 +02:00
|
|
|
if v == nil {
|
|
|
|
http.Error(w, "foo does not exist in session", 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write([]byte(v.(string)))
|
|
|
|
}))
|
|
|
|
|
2019-06-18 12:49:37 +02:00
|
|
|
ts := newTestServer(t, sessionManager.LoadAndSave(mux))
|
2019-04-28 07:30:35 +02:00
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
ts.execute(t, "/put")
|
|
|
|
header, _ := ts.execute(t, "/destroy")
|
|
|
|
cookie := header.Get("Set-Cookie")
|
|
|
|
|
2019-06-18 12:49:37 +02:00
|
|
|
if strings.HasPrefix(cookie, fmt.Sprintf("%s=;", sessionManager.Cookie.Name)) == false {
|
|
|
|
t.Fatalf("got %q: expected prefix %q", cookie, fmt.Sprintf("%s=;", sessionManager.Cookie.Name))
|
2017-10-07 19:03:35 +02:00
|
|
|
}
|
2019-04-28 07:30:35 +02:00
|
|
|
if strings.Contains(cookie, "Expires=Thu, 01 Jan 1970 00:00:01 GMT") == false {
|
|
|
|
t.Fatalf("got %q: expected to contain %q", cookie, "Expires=Thu, 01 Jan 1970 00:00:01 GMT")
|
2017-10-07 19:03:35 +02:00
|
|
|
}
|
2019-04-28 07:30:35 +02:00
|
|
|
if strings.Contains(cookie, "Max-Age=0") == false {
|
|
|
|
t.Fatalf("got %q: expected to contain %q", cookie, "Max-Age=0")
|
2017-10-07 19:03:35 +02:00
|
|
|
}
|
|
|
|
|
2019-04-28 07:30:35 +02:00
|
|
|
_, body := ts.execute(t, "/get")
|
|
|
|
if body != "foo does not exist in session\n" {
|
|
|
|
t.Errorf("want %q; got %q", "foo does not exist in session\n", body)
|
2017-10-07 19:03:35 +02:00
|
|
|
}
|
|
|
|
}
|
2019-06-21 13:35:08 +02:00
|
|
|
|
|
|
|
func TestRenewToken(t *testing.T) {
|
|
|
|
sessionManager := New()
|
|
|
|
|
|
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("/put", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
sessionManager.Put(r.Context(), "foo", "bar")
|
|
|
|
}))
|
|
|
|
mux.HandleFunc("/renew", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
err := sessionManager.RenewToken(r.Context())
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
mux.HandleFunc("/get", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
v := sessionManager.Get(r.Context(), "foo")
|
|
|
|
if v == nil {
|
|
|
|
http.Error(w, "foo does not exist in session", 500)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write([]byte(v.(string)))
|
|
|
|
}))
|
|
|
|
|
|
|
|
ts := newTestServer(t, sessionManager.LoadAndSave(mux))
|
|
|
|
defer ts.Close()
|
|
|
|
|
|
|
|
header, _ := ts.execute(t, "/put")
|
|
|
|
cookie := header.Get("Set-Cookie")
|
|
|
|
originalToken := extractTokenFromCookie(cookie)
|
|
|
|
|
|
|
|
header, _ = ts.execute(t, "/renew")
|
|
|
|
cookie = header.Get("Set-Cookie")
|
|
|
|
newToken := extractTokenFromCookie(cookie)
|
|
|
|
|
|
|
|
if newToken == originalToken {
|
|
|
|
t.Fatal("token has not changed")
|
|
|
|
}
|
|
|
|
|
|
|
|
header, body := ts.execute(t, "/get")
|
|
|
|
if body != "bar" {
|
|
|
|
t.Errorf("want %q; got %q", "bar", body)
|
|
|
|
}
|
|
|
|
}
|