|
|
|
@ -10,39 +10,59 @@ import ( |
|
|
|
"time" |
|
|
|
) |
|
|
|
|
|
|
|
var ( |
|
|
|
mutex sync.Mutex |
|
|
|
data = make(map[*http.Request]map[interface{}]interface{}) |
|
|
|
datat = make(map[*http.Request]int64) |
|
|
|
) |
|
|
|
var globalContext *Context = NewContext() |
|
|
|
|
|
|
|
type Context struct { |
|
|
|
mutex sync.RWMutex |
|
|
|
data map[*http.Request]map[interface{}]interface{} |
|
|
|
datat map[*http.Request]int64 |
|
|
|
} |
|
|
|
|
|
|
|
func NewContext() *Context { |
|
|
|
data := make(map[*http.Request]map[interface{}]interface{}) |
|
|
|
datat := make(map[*http.Request]int64) |
|
|
|
return &Context{data: data, datat: datat} |
|
|
|
} |
|
|
|
|
|
|
|
// Set stores a value for a given key in a given request.
|
|
|
|
func Set(r *http.Request, key, val interface{}) { |
|
|
|
mutex.Lock() |
|
|
|
defer mutex.Unlock() |
|
|
|
if data[r] == nil { |
|
|
|
data[r] = make(map[interface{}]interface{}) |
|
|
|
datat[r] = time.Now().Unix() |
|
|
|
globalContext.Set(r, key, val) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Context) Set(r *http.Request, key, val interface{}) { |
|
|
|
c.mutex.Lock() |
|
|
|
defer c.mutex.Unlock() |
|
|
|
if c.data[r] == nil { |
|
|
|
c.data[r] = make(map[interface{}]interface{}) |
|
|
|
c.datat[r] = time.Now().Unix() |
|
|
|
} |
|
|
|
data[r][key] = val |
|
|
|
c.data[r][key] = val |
|
|
|
} |
|
|
|
|
|
|
|
// Get returns a value stored for a given key in a given request.
|
|
|
|
func Get(r *http.Request, key interface{}) interface{} { |
|
|
|
mutex.Lock() |
|
|
|
defer mutex.Unlock() |
|
|
|
if data[r] != nil { |
|
|
|
return data[r][key] |
|
|
|
return globalContext.Get(r, key) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Context) Get(r *http.Request, key interface{}) interface{} { |
|
|
|
c.mutex.RLock() |
|
|
|
defer c.mutex.RUnlock() |
|
|
|
if c.data[r] != nil { |
|
|
|
return c.data[r][key] |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
// Delete removes a value stored for a given key in a given request.
|
|
|
|
func Delete(r *http.Request, key interface{}) { |
|
|
|
mutex.Lock() |
|
|
|
defer mutex.Unlock() |
|
|
|
if data[r] != nil { |
|
|
|
delete(data[r], key) |
|
|
|
globalContext.Delete(r, key) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Context) Delete(r *http.Request, key interface{}) { |
|
|
|
c.mutex.Lock() |
|
|
|
defer c.mutex.Unlock() |
|
|
|
if c.data[r] != nil { |
|
|
|
delete(c.data[r], key) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -51,15 +71,19 @@ func Delete(r *http.Request, key interface{}) { |
|
|
|
// This is usually called by a handler wrapper to clean up request
|
|
|
|
// variables at the end of a request lifetime. See ClearHandler().
|
|
|
|
func Clear(r *http.Request) { |
|
|
|
mutex.Lock() |
|
|
|
defer mutex.Unlock() |
|
|
|
clear(r) |
|
|
|
globalContext.Clear(r) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Context) Clear(r *http.Request) { |
|
|
|
c.mutex.Lock() |
|
|
|
defer c.mutex.Unlock() |
|
|
|
c.clear(r) |
|
|
|
} |
|
|
|
|
|
|
|
// clear is Clear without the lock.
|
|
|
|
func clear(r *http.Request) { |
|
|
|
delete(data, r) |
|
|
|
delete(datat, r) |
|
|
|
func (c *Context) clear(r *http.Request) { |
|
|
|
delete(c.data, r) |
|
|
|
delete(c.datat, r) |
|
|
|
} |
|
|
|
|
|
|
|
// Purge removes request data stored for longer than maxAge, in seconds.
|
|
|
|
@ -72,18 +96,22 @@ func clear(r *http.Request) { |
|
|
|
// amount of memory. In case this is detected, Purge() must be called
|
|
|
|
// periodically until the problem is fixed.
|
|
|
|
func Purge(maxAge int) int { |
|
|
|
mutex.Lock() |
|
|
|
defer mutex.Unlock() |
|
|
|
return globalContext.Purge(maxAge) |
|
|
|
} |
|
|
|
|
|
|
|
func (c *Context) Purge(maxAge int) int { |
|
|
|
c.mutex.Lock() |
|
|
|
defer c.mutex.Unlock() |
|
|
|
count := 0 |
|
|
|
if maxAge <= 0 { |
|
|
|
count = len(data) |
|
|
|
data = make(map[*http.Request]map[interface{}]interface{}) |
|
|
|
datat = make(map[*http.Request]int64) |
|
|
|
count = len(c.data) |
|
|
|
c.data = make(map[*http.Request]map[interface{}]interface{}) |
|
|
|
c.datat = make(map[*http.Request]int64) |
|
|
|
} else { |
|
|
|
min := time.Now().Unix() - int64(maxAge) |
|
|
|
for r, _ := range data { |
|
|
|
if datat[r] < min { |
|
|
|
clear(r) |
|
|
|
for r, _ := range c.data { |
|
|
|
if c.datat[r] < min { |
|
|
|
c.clear(r) |
|
|
|
count++ |
|
|
|
} |
|
|
|
} |
|
|
|
|