replace zxq.co/ripple/hanayo

This commit is contained in:
Alicia
2019-02-23 13:29:15 +00:00
commit c3d206c173
5871 changed files with 1353715 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
{
"ImportPath": "github.com/gin-gonic/contrib/sessions",
"GoVersion": "go1.3",
"Deps": [
{
"ImportPath": "github.com/boj/redistore",
"Rev": "0cd55584b172cefd31c4cb84e2904585d898c7b2"
},
{
"ImportPath": "github.com/gin-gonic/gin",
"Rev": "ac0ad2fed865d40a0adc1ac3ccaadc3acff5db4b"
},
{
"ImportPath": "github.com/gorilla/sessions",
"Rev": "f61c3ec2cf65d69e7efedfd4d060fe128882c951"
}
]
}

View File

@@ -0,0 +1,70 @@
# sessions
Gin middleware for session management with multi-backend support (currently cookie, Redis).
## Examples
#### cookie-based
```go
package main
import (
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store := sessions.NewCookieStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count += 1
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}
```
#### Redis
```go
package main
import (
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store, _ := sessions.NewRedisStore(10, "tcp", "localhost:6379", "", []byte("secret"))
r.Use(sessions.Sessions("session", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count += 1
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}
```

View File

@@ -0,0 +1,36 @@
package sessions
import (
"github.com/gorilla/sessions"
)
type CookieStore interface {
Store
}
// Keys are defined in pairs to allow key rotation, but the common case is to set a single
// authentication key and optionally an encryption key.
//
// The first key in a pair is used for authentication and the second for encryption. The
// encryption key can be set to nil or omitted in the last pair, but the authentication key
// is required in all pairs.
//
// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key,
// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewCookieStore(keyPairs ...[]byte) CookieStore {
return &cookieStore{sessions.NewCookieStore(keyPairs...)}
}
type cookieStore struct {
*sessions.CookieStore
}
func (c *cookieStore) Options(options Options) {
c.CookieStore.Options = &sessions.Options{
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
}
}

View File

@@ -0,0 +1,30 @@
package sessions
import (
"testing"
)
var newCookieStore = func(_ *testing.T) Store {
store := NewCookieStore([]byte("secret"))
return store
}
func TestCookie_SessionGetSet(t *testing.T) {
sessionGetSet(t, newCookieStore)
}
func TestCookie_SessionDeleteKey(t *testing.T) {
sessionDeleteKey(t, newCookieStore)
}
func TestCookie_SessionFlashes(t *testing.T) {
sessionFlashes(t, newCookieStore)
}
func TestCookie_SessionClear(t *testing.T) {
sessionClear(t, newCookieStore)
}
func TestCookie_SessionOptions(t *testing.T) {
sessionOptions(t, newCookieStore)
}

View File

@@ -0,0 +1,28 @@
package maincookie
import (
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store := sessions.NewCookieStore([]byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count += 1
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}

View File

@@ -0,0 +1,28 @@
package mainredis
import (
"github.com/gin-gonic/contrib/sessions"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
store, _ := sessions.NewRedisStore(10, "tcp", "localhost:6379", "", []byte("secret"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count += 1
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}

45
vendor/github.com/johnniedoe/contrib/sessions/redis.go generated vendored Normal file
View File

@@ -0,0 +1,45 @@
package sessions
import (
"github.com/boj/redistore"
"github.com/gorilla/sessions"
)
type RedisStore interface {
Store
}
// size: maximum number of idle connections.
// network: tcp or udp
// address: host:port
// password: redis-password
// Keys are defined in pairs to allow key rotation, but the common case is to set a single
// authentication key and optionally an encryption key.
//
// The first key in a pair is used for authentication and the second for encryption. The
// encryption key can be set to nil or omitted in the last pair, but the authentication key
// is required in all pairs.
//
// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key,
// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewRedisStore(size int, network, address, password string, keyPairs ...[]byte) (RedisStore, error) {
store, err := redistore.NewRediStore(size, network, address, password, keyPairs...)
if err != nil {
return nil, err
}
return &redisStore{store}, nil
}
type redisStore struct {
*redistore.RediStore
}
func (c *redisStore) Options(options Options) {
c.RediStore.Options = &sessions.Options{
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
}
}

View File

@@ -0,0 +1,35 @@
package sessions
import (
"testing"
)
const redisTestServer = "localhost:6379"
var newRedisStore = func(_ *testing.T) Store {
store, err := NewRedisStore(10, "tcp", redisTestServer, "", []byte("secret"))
if err != nil {
panic(err)
}
return store
}
func TestRedis_SessionGetSet(t *testing.T) {
sessionGetSet(t, newRedisStore)
}
func TestRedis_SessionDeleteKey(t *testing.T) {
sessionDeleteKey(t, newRedisStore)
}
func TestRedis_SessionFlashes(t *testing.T) {
sessionFlashes(t, newRedisStore)
}
func TestRedis_SessionClear(t *testing.T) {
sessionClear(t, newRedisStore)
}
func TestRedis_SessionOptions(t *testing.T) {
sessionOptions(t, newRedisStore)
}

View File

@@ -0,0 +1,147 @@
package sessions
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/gorilla/context"
"github.com/gorilla/sessions"
)
const (
DefaultKey = "github.com/gin-gonic/contrib/sessions"
errorFormat = "[sessions] ERROR! %s\n"
)
type Store interface {
sessions.Store
Options(Options)
}
// Options stores configuration for a session or session store.
// Fields are a subset of http.Cookie fields.
type Options struct {
Path string
Domain string
// MaxAge=0 means no 'Max-Age' attribute specified.
// MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0'.
// MaxAge>0 means Max-Age attribute present and given in seconds.
MaxAge int
Secure bool
HttpOnly bool
}
// Wraps thinly gorilla-session methods.
// Session stores the values and optional configuration for a session.
type Session interface {
// Get returns the session value associated to the given key.
Get(key interface{}) interface{}
// Set sets the session value associated to the given key.
Set(key interface{}, val interface{})
// Delete removes the session value associated to the given key.
Delete(key interface{})
// Clear deletes all values in the session.
Clear()
// AddFlash adds a flash message to the session.
// A single variadic argument is accepted, and it is optional: it defines the flash key.
// If not defined "_flash" is used by default.
AddFlash(value interface{}, vars ...string)
// Flashes returns a slice of flash messages from the session.
// A single variadic argument is accepted, and it is optional: it defines the flash key.
// If not defined "_flash" is used by default.
Flashes(vars ...string) []interface{}
// Options sets confuguration for a session.
Options(Options)
// Save saves all sessions used during the current request.
Save() error
}
func Sessions(name string, store Store) gin.HandlerFunc {
return func(c *gin.Context) {
s := &session{name, c.Request, store, nil, false, c.Writer}
c.Set(DefaultKey, s)
defer context.Clear(c.Request)
c.Next()
}
}
type session struct {
name string
request *http.Request
store Store
session *sessions.Session
written bool
writer http.ResponseWriter
}
func (s *session) Get(key interface{}) interface{} {
return s.Session().Values[key]
}
func (s *session) Set(key interface{}, val interface{}) {
s.Session().Values[key] = val
s.written = true
}
func (s *session) Delete(key interface{}) {
delete(s.Session().Values, key)
s.written = true
}
func (s *session) Clear() {
for key := range s.Session().Values {
s.Delete(key)
}
}
func (s *session) AddFlash(value interface{}, vars ...string) {
s.Session().AddFlash(value, vars...)
s.written = true
}
func (s *session) Flashes(vars ...string) []interface{} {
s.written = true
return s.Session().Flashes(vars...)
}
func (s *session) Options(options Options) {
s.Session().Options = &sessions.Options{
Path: options.Path,
Domain: options.Domain,
MaxAge: options.MaxAge,
Secure: options.Secure,
HttpOnly: options.HttpOnly,
}
}
func (s *session) Save() error {
if s.Written() {
e := s.Session().Save(s.request, s.writer)
if e == nil {
s.written = false
}
return e
}
return nil
}
func (s *session) Session() *sessions.Session {
if s.session == nil {
var err error
s.session, err = s.store.Get(s.request, s.name)
if err != nil {
log.Printf(errorFormat, err)
}
}
return s.session
}
func (s *session) Written() bool {
return s.written
}
// shortcut to get session
func Default(c *gin.Context) Session {
return c.MustGet(DefaultKey).(Session)
}

View File

@@ -0,0 +1,219 @@
package sessions
import (
"github.com/gin-gonic/gin"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
type storeFactory func(*testing.T) Store
const sessionName = "mysession"
const ok = "ok"
func sessionGetSet(t *testing.T, newStore storeFactory) {
r := gin.Default()
r.Use(Sessions(sessionName, newStore(t)))
r.GET("/set", func(c *gin.Context) {
session := Default(c)
session.Set("key", ok)
session.Save()
c.String(200, ok)
})
r.GET("/get", func(c *gin.Context) {
session := Default(c)
if session.Get("key") != ok {
t.Error("Session writing failed")
}
session.Save()
c.String(200, ok)
})
res1 := httptest.NewRecorder()
req1, _ := http.NewRequest("GET", "/set", nil)
r.ServeHTTP(res1, req1)
res2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/get", nil)
req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie"))
r.ServeHTTP(res2, req2)
}
func sessionDeleteKey(t *testing.T, newStore storeFactory) {
r := gin.Default()
r.Use(Sessions(sessionName, newStore(t)))
r.GET("/set", func(c *gin.Context) {
session := Default(c)
session.Set("key", ok)
session.Save()
c.String(200, ok)
})
r.GET("/delete", func(c *gin.Context) {
session := Default(c)
session.Delete("key")
session.Save()
c.String(200, ok)
})
r.GET("/get", func(c *gin.Context) {
session := Default(c)
if session.Get("key") != nil {
t.Error("Session deleting failed")
}
session.Save()
c.String(200, ok)
})
res1 := httptest.NewRecorder()
req1, _ := http.NewRequest("GET", "/set", nil)
r.ServeHTTP(res1, req1)
res2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/delete", nil)
req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie"))
r.ServeHTTP(res2, req2)
res3 := httptest.NewRecorder()
req3, _ := http.NewRequest("GET", "/get", nil)
req3.Header.Set("Cookie", res2.Header().Get("Set-Cookie"))
r.ServeHTTP(res3, req3)
}
func sessionFlashes(t *testing.T, newStore storeFactory) {
r := gin.Default()
store := newStore(t)
store.Options(Options{
Domain: "localhost",
})
r.Use(Sessions(sessionName, store))
r.GET("/set", func(c *gin.Context) {
session := Default(c)
session.AddFlash(ok)
session.Save()
c.String(200, ok)
})
r.GET("/flash", func(c *gin.Context) {
session := Default(c)
l := len(session.Flashes())
if l != 1 {
t.Error("Flashes count does not equal 1. Equals ", l)
}
session.Save()
c.String(200, ok)
})
r.GET("/check", func(c *gin.Context) {
session := Default(c)
l := len(session.Flashes())
if l != 0 {
t.Error("flashes count is not 0 after reading. Equals ", l)
}
session.Save()
c.String(200, ok)
})
res1 := httptest.NewRecorder()
req1, _ := http.NewRequest("GET", "/set", nil)
r.ServeHTTP(res1, req1)
res2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/flash", nil)
req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie"))
r.ServeHTTP(res2, req2)
res3 := httptest.NewRecorder()
req3, _ := http.NewRequest("GET", "/check", nil)
req3.Header.Set("Cookie", res2.Header().Get("Set-Cookie"))
r.ServeHTTP(res3, req3)
}
func sessionClear(t *testing.T, newStore storeFactory) {
data := map[string]string{
"key": "val",
"foo": "bar",
}
r := gin.Default()
store := newStore(t)
r.Use(Sessions(sessionName, store))
r.GET("/set", func(c *gin.Context) {
session := Default(c)
for k, v := range data {
session.Set(k, v)
}
session.Clear()
session.Save()
c.String(200, ok)
})
r.GET("/check", func(c *gin.Context) {
session := Default(c)
for k, v := range data {
if session.Get(k) == v {
t.Fatal("Session clear failed")
}
}
session.Save()
c.String(200, ok)
})
res1 := httptest.NewRecorder()
req1, _ := http.NewRequest("GET", "/set", nil)
r.ServeHTTP(res1, req1)
res2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/check", nil)
req2.Header.Set("Cookie", res1.Header().Get("Set-Cookie"))
r.ServeHTTP(res2, req2)
}
func sessionOptions(t *testing.T, newStore storeFactory) {
r := gin.Default()
store := newStore(t)
store.Options(Options{
Domain: "localhost",
})
r.Use(Sessions(sessionName, store))
r.GET("/domain", func(c *gin.Context) {
session := Default(c)
session.Set("key", ok)
session.Options(Options{
Path: "/foo/bar/bat",
})
session.Save()
c.String(200, ok)
})
r.GET("/path", func(c *gin.Context) {
session := Default(c)
session.Set("key", ok)
session.Save()
c.String(200, ok)
})
res1 := httptest.NewRecorder()
req1, _ := http.NewRequest("GET", "/domain", nil)
r.ServeHTTP(res1, req1)
res2 := httptest.NewRecorder()
req2, _ := http.NewRequest("GET", "/path", nil)
r.ServeHTTP(res2, req2)
s := strings.Split(res1.Header().Get("Set-Cookie"), ";")
if s[1] != " Path=/foo/bar/bat" {
t.Error("Error writing path with options:", s[1])
}
s = strings.Split(res2.Header().Get("Set-Cookie"), ";")
if s[1] != " Domain=localhost" {
t.Error("Error writing domain with options:", s[1])
}
}