context.go (3583B)
1 // Copyright 2012 The Gorilla Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package context 6 7 import ( 8 "net/http" 9 "sync" 10 "time" 11 ) 12 13 var ( 14 mutex sync.RWMutex 15 data = make(map[*http.Request]map[interface{}]interface{}) 16 datat = make(map[*http.Request]int64) 17 ) 18 19 // Set stores a value for a given key in a given request. 20 func Set(r *http.Request, key, val interface{}) { 21 mutex.Lock() 22 if data[r] == nil { 23 data[r] = make(map[interface{}]interface{}) 24 datat[r] = time.Now().Unix() 25 } 26 data[r][key] = val 27 mutex.Unlock() 28 } 29 30 // Get returns a value stored for a given key in a given request. 31 func Get(r *http.Request, key interface{}) interface{} { 32 mutex.RLock() 33 if ctx := data[r]; ctx != nil { 34 value := ctx[key] 35 mutex.RUnlock() 36 return value 37 } 38 mutex.RUnlock() 39 return nil 40 } 41 42 // GetOk returns stored value and presence state like multi-value return of map access. 43 func GetOk(r *http.Request, key interface{}) (interface{}, bool) { 44 mutex.RLock() 45 if _, ok := data[r]; ok { 46 value, ok := data[r][key] 47 mutex.RUnlock() 48 return value, ok 49 } 50 mutex.RUnlock() 51 return nil, false 52 } 53 54 // GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. 55 func GetAll(r *http.Request) map[interface{}]interface{} { 56 mutex.RLock() 57 if context, ok := data[r]; ok { 58 result := make(map[interface{}]interface{}, len(context)) 59 for k, v := range context { 60 result[k] = v 61 } 62 mutex.RUnlock() 63 return result 64 } 65 mutex.RUnlock() 66 return nil 67 } 68 69 // GetAllOk returns all stored values for the request as a map and a boolean value that indicates if 70 // the request was registered. 71 func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { 72 mutex.RLock() 73 context, ok := data[r] 74 result := make(map[interface{}]interface{}, len(context)) 75 for k, v := range context { 76 result[k] = v 77 } 78 mutex.RUnlock() 79 return result, ok 80 } 81 82 // Delete removes a value stored for a given key in a given request. 83 func Delete(r *http.Request, key interface{}) { 84 mutex.Lock() 85 if data[r] != nil { 86 delete(data[r], key) 87 } 88 mutex.Unlock() 89 } 90 91 // Clear removes all values stored for a given request. 92 // 93 // This is usually called by a handler wrapper to clean up request 94 // variables at the end of a request lifetime. See ClearHandler(). 95 func Clear(r *http.Request) { 96 mutex.Lock() 97 clear(r) 98 mutex.Unlock() 99 } 100 101 // clear is Clear without the lock. 102 func clear(r *http.Request) { 103 delete(data, r) 104 delete(datat, r) 105 } 106 107 // Purge removes request data stored for longer than maxAge, in seconds. 108 // It returns the amount of requests removed. 109 // 110 // If maxAge <= 0, all request data is removed. 111 // 112 // This is only used for sanity check: in case context cleaning was not 113 // properly set some request data can be kept forever, consuming an increasing 114 // amount of memory. In case this is detected, Purge() must be called 115 // periodically until the problem is fixed. 116 func Purge(maxAge int) int { 117 mutex.Lock() 118 count := 0 119 if maxAge <= 0 { 120 count = len(data) 121 data = make(map[*http.Request]map[interface{}]interface{}) 122 datat = make(map[*http.Request]int64) 123 } else { 124 min := time.Now().Unix() - int64(maxAge) 125 for r := range data { 126 if datat[r] < min { 127 clear(r) 128 count++ 129 } 130 } 131 } 132 mutex.Unlock() 133 return count 134 } 135 136 // ClearHandler wraps an http.Handler and clears request values at the end 137 // of a request lifetime. 138 func ClearHandler(h http.Handler) http.Handler { 139 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 140 defer Clear(r) 141 h.ServeHTTP(w, r) 142 }) 143 }