From 6c54e73dbdcaa3a0bb56d80934c8b46590320fcf Mon Sep 17 00:00:00 2001 From: John Date: Tue, 5 Nov 2019 17:33:06 +0800 Subject: [PATCH] add example for memory storage og gsession --- .example/os/gsession/storage-memory/memory.go | 30 ++++++ .../redis-hashtable.go | 2 +- os/gsession/gsession.go | 5 + os/gsession/gsession_storage.go | 5 - os/gsession/gsession_storage_memory.go | 94 +++++++++++++++++++ .../gsession_storage_redis_hashtable.go | 13 ++- .../gsession_unit_storage_memory_test.go | 74 +++++++++++++++ os/gview/gview.go | 2 + os/gview/gview_doparse.go | 2 +- 9 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 .example/os/gsession/storage-memory/memory.go create mode 100644 os/gsession/gsession_storage_memory.go create mode 100644 os/gsession/gsession_unit_storage_memory_test.go diff --git a/.example/os/gsession/storage-memory/memory.go b/.example/os/gsession/storage-memory/memory.go new file mode 100644 index 000000000..78697f99e --- /dev/null +++ b/.example/os/gsession/storage-memory/memory.go @@ -0,0 +1,30 @@ +package main + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gsession" + "github.com/gogf/gf/os/gtime" + "time" +) + +func main() { + s := g.Server() + s.SetConfigWithMap(g.Map{ + "SessionMaxAge": time.Minute, + "SessionStorage": gsession.NewStorageMemory(), + }) + s.BindHandler("/set", func(r *ghttp.Request) { + r.Session.Set("time", gtime.Second()) + r.Response.Write("ok") + }) + s.BindHandler("/get", func(r *ghttp.Request) { + r.Response.Write(r.Session.Map()) + }) + s.BindHandler("/del", func(r *ghttp.Request) { + r.Session.Clear() + r.Response.Write("ok") + }) + s.SetPort(8199) + s.Run() +} diff --git a/.example/os/gsession/storage-redis-hashtable/redis-hashtable.go b/.example/os/gsession/storage-redis-hashtable/redis-hashtable.go index 3e5d77190..3c1b8530a 100644 --- a/.example/os/gsession/storage-redis-hashtable/redis-hashtable.go +++ b/.example/os/gsession/storage-redis-hashtable/redis-hashtable.go @@ -11,7 +11,7 @@ import ( func main() { s := g.Server() s.SetConfigWithMap(g.Map{ - "SessionMaxAge": 60 * time.Minute, + "SessionMaxAge": time.Minute, "SessionStorage": gsession.NewStorageRedisHashTable(g.Redis()), }) s.BindHandler("/set", func(r *ghttp.Request) { diff --git a/os/gsession/gsession.go b/os/gsession/gsession.go index 0f312af10..03c6db025 100644 --- a/os/gsession/gsession.go +++ b/os/gsession/gsession.go @@ -8,6 +8,7 @@ package gsession import ( + "errors" "strconv" "strings" @@ -15,6 +16,10 @@ import ( "github.com/gogf/gf/util/grand" ) +var ( + ErrorDisabled = errors.New("this feature is disabled in this storage") +) + // NewSessionId creates and returns a new and unique session id string, // the length of which is 18 bytes. func NewSessionId() string { diff --git a/os/gsession/gsession_storage.go b/os/gsession/gsession_storage.go index 17ab8e0c8..23b2783c1 100644 --- a/os/gsession/gsession_storage.go +++ b/os/gsession/gsession_storage.go @@ -7,7 +7,6 @@ package gsession import ( - "errors" "github.com/gogf/gf/container/gmap" "time" ) @@ -59,7 +58,3 @@ type Storage interface { // This function is called ever after session, which is not dirty, is closed. UpdateTTL(id string, ttl time.Duration) error } - -var ( - ErrorDisabled = errors.New("this feature is disabled in this storage") -) diff --git a/os/gsession/gsession_storage_memory.go b/os/gsession/gsession_storage_memory.go new file mode 100644 index 000000000..24786e745 --- /dev/null +++ b/os/gsession/gsession_storage_memory.go @@ -0,0 +1,94 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gsession + +import ( + "github.com/gogf/gf/container/gmap" + "time" +) + +// StorageMemory implements the Session Storage interface with memory. +type StorageMemory struct{} + +// NewStorageMemory creates and returns a file storage object for session. +func NewStorageMemory() *StorageMemory { + return &StorageMemory{} +} + +// New creates a session id. +// This function can be used for custom session creation. +func (s *StorageMemory) New(ttl time.Duration) (id string) { + return "" +} + +// Get retrieves session value with given key. +// It returns nil if the key does not exist in the session. +func (s *StorageMemory) Get(id string, key string) interface{} { + return nil +} + +// GetMap retrieves all key-value pairs as map from storage. +func (s *StorageMemory) GetMap(id string) map[string]interface{} { + return nil +} + +// GetSize retrieves the size of key-value pairs from storage. +func (s *StorageMemory) GetSize(id string) int { + return -1 +} + +// Set sets key-value session pair to the storage. +// The parameter specifies the TTL for the session id (not for the key-value pair). +func (s *StorageMemory) Set(id string, key string, value interface{}, ttl time.Duration) error { + return ErrorDisabled +} + +// SetMap batch sets key-value session pairs with map to the storage. +// The parameter specifies the TTL for the session id(not for the key-value pair). +func (s *StorageMemory) SetMap(id string, data map[string]interface{}, ttl time.Duration) error { + return ErrorDisabled +} + +// Remove deletes key with its value from storage. +func (s *StorageMemory) Remove(id string, key string) error { + return ErrorDisabled +} + +// RemoveAll deletes all key-value pairs from storage. +func (s *StorageMemory) RemoveAll(id string) error { + return ErrorDisabled +} + +// GetSession returns the session data as *gmap.StrAnyMap for given session id from storage. +// +// The parameter specifies the TTL for this session, and it returns nil if the TTL is exceeded. +// The parameter is the current old session data stored in memory, +// and for some storage it might be nil if memory storage is disabled. +// +// This function is called ever when session starts. +func (s *StorageMemory) GetSession(id string, ttl time.Duration, data *gmap.StrAnyMap) (*gmap.StrAnyMap, error) { + return data, nil +} + +// SetSession updates the data map for specified session id. +// This function is called ever after session, which is changed dirty, is closed. +// This copy all session data map from memory to storage. +func (s *StorageMemory) SetSession(id string, data *gmap.StrAnyMap, ttl time.Duration) error { + return nil +} + +// UpdateTTL updates the TTL for specified session id. +// This function is called ever after session, which is not dirty, is closed. +// It just adds the session id to the async handling queue. +func (s *StorageMemory) UpdateTTL(id string, ttl time.Duration) error { + return nil +} + +// doUpdateTTL updates the TTL for session id. +func (s *StorageMemory) doUpdateTTL(id string) error { + return nil +} diff --git a/os/gsession/gsession_storage_redis_hashtable.go b/os/gsession/gsession_storage_redis_hashtable.go index f7537f671..cd8fec536 100644 --- a/os/gsession/gsession_storage_redis_hashtable.go +++ b/os/gsession/gsession_storage_redis_hashtable.go @@ -44,8 +44,11 @@ func (s *StorageRedisHashTable) New(ttl time.Duration) (id string) { // Get retrieves session value with given key. // It returns nil if the key does not exist in the session. func (s *StorageRedisHashTable) Get(id string, key string) interface{} { - r, _ := s.redis.DoVar("HGET", s.key(id), key) - return r.String() + r, _ := s.redis.Do("HGET", s.key(id), key) + if r != nil { + return gconv.String(r) + } + return r } // GetMap retrieves all key-value pairs as map from storage. @@ -57,7 +60,11 @@ func (s *StorageRedisHashTable) GetMap(id string) map[string]interface{} { array := r.Interfaces() m := make(map[string]interface{}) for i := 0; i < len(array); i += 2 { - m[gconv.String(array[i])] = gconv.String(array[i+1]) + if array[i+1] != nil { + m[gconv.String(array[i])] = gconv.String(array[i+1]) + } else { + m[gconv.String(array[i])] = array[i+1] + } } return m } diff --git a/os/gsession/gsession_unit_storage_memory_test.go b/os/gsession/gsession_unit_storage_memory_test.go new file mode 100644 index 000000000..6fe896594 --- /dev/null +++ b/os/gsession/gsession_unit_storage_memory_test.go @@ -0,0 +1,74 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gsession_test + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gsession" + "testing" + "time" + + "github.com/gogf/gf/test/gtest" +) + +func Test_StorageMemory(t *testing.T) { + storage := gsession.NewStorageMemory() + manager := gsession.New(time.Second, storage) + sessionId := "" + gtest.Case(t, func() { + s := manager.New() + defer s.Close() + s.Set("k1", "v1") + s.Set("k2", "v2") + s.Sets(g.Map{ + "k3": "v3", + "k4": "v4", + }) + gtest.Assert(s.IsDirty(), true) + sessionId = s.Id() + }) + + time.Sleep(500 * time.Millisecond) + gtest.Case(t, func() { + s := manager.New(sessionId) + gtest.Assert(s.Get("k1"), "v1") + gtest.Assert(s.Get("k2"), "v2") + gtest.Assert(s.Get("k3"), "v3") + gtest.Assert(s.Get("k4"), "v4") + gtest.Assert(len(s.Map()), 4) + gtest.Assert(s.Map()["k1"], "v1") + gtest.Assert(s.Map()["k4"], "v4") + gtest.Assert(s.Id(), sessionId) + gtest.Assert(s.Size(), 4) + gtest.Assert(s.Contains("k1"), true) + gtest.Assert(s.Contains("k3"), true) + gtest.Assert(s.Contains("k5"), false) + s.Remove("k4") + gtest.Assert(s.Size(), 3) + gtest.Assert(s.Contains("k3"), true) + gtest.Assert(s.Contains("k4"), false) + s.RemoveAll() + gtest.Assert(s.Size(), 0) + gtest.Assert(s.Contains("k1"), false) + gtest.Assert(s.Contains("k2"), false) + s.Sets(g.Map{ + "k5": "v5", + "k6": "v6", + }) + gtest.Assert(s.Size(), 2) + gtest.Assert(s.Contains("k5"), true) + gtest.Assert(s.Contains("k6"), true) + }) + + time.Sleep(1000 * time.Millisecond) + gtest.Case(t, func() { + s := manager.New(sessionId) + gtest.Assert(s.Size(), 0) + gtest.Assert(s.Get("k5"), nil) + gtest.Assert(s.Get("k6"), nil) + }) +} diff --git a/os/gview/gview.go b/os/gview/gview.go index 602259483..58f594099 100644 --- a/os/gview/gview.go +++ b/os/gview/gview.go @@ -190,6 +190,7 @@ func (view *View) SetPath(path string) error { } view.paths.Clear() view.paths.Append(realPath) + view.fileCacheMap.Clear() //glog.Debug("[gview] SetPath:", realPath) return nil } @@ -240,5 +241,6 @@ func (view *View) AddPath(path string) error { return nil } view.paths.Append(realPath) + view.fileCacheMap.Clear() return nil } diff --git a/os/gview/gview_doparse.go b/os/gview/gview_doparse.go index 624995472..cead95ec5 100644 --- a/os/gview/gview_doparse.go +++ b/os/gview/gview_doparse.go @@ -63,7 +63,7 @@ func (view *View) Parse(file string, params ...Params) (result string, err error // Searching the absolute file path for . path, folder, resource, err = view.searchFile(file) if err != nil { - return "" + return nil } if resource != nil { content = gconv.UnsafeBytesToStr(resource.Content())