mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-10-31 10:07:15 +08:00 
			
		
		
		
	fix (concurrency): fix concurrency problem
This commit is contained in:
		| @ -4,6 +4,7 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"github.com/mitchellh/hashstructure" | 	"github.com/mitchellh/hashstructure" | ||||||
| 	"github.com/patrickmn/go-cache" | 	"github.com/patrickmn/go-cache" | ||||||
|  | 	"sync" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -60,6 +61,7 @@ func NewAppCache(arg ...time.Duration) AppCache { | |||||||
|  |  | ||||||
| type KeyValueStore struct { | type KeyValueStore struct { | ||||||
| 	cache map[string]interface{} | 	cache map[string]interface{} | ||||||
|  | 	sync.RWMutex | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewKeyValueStore() KeyValueStore { | func NewKeyValueStore() KeyValueStore { | ||||||
| @ -67,13 +69,19 @@ func NewKeyValueStore() KeyValueStore { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (this KeyValueStore) Get(key string) interface{} { | func (this KeyValueStore) Get(key string) interface{} { | ||||||
|  | 	this.RLock() | ||||||
|  | 	defer this.RUnlock() | ||||||
| 	return this.cache[key] | 	return this.cache[key] | ||||||
| } | } | ||||||
|  |  | ||||||
| func (this *KeyValueStore) Set(key string, value interface{}) { | func (this *KeyValueStore) Set(key string, value interface{}) { | ||||||
|  | 	this.Lock() | ||||||
|  | 	defer this.Unlock() | ||||||
| 	this.cache[key] = value | 	this.cache[key] = value | ||||||
| } | } | ||||||
|  |  | ||||||
| func (this *KeyValueStore) Clear() { | func (this *KeyValueStore) Clear() { | ||||||
|  | 	this.Lock() | ||||||
|  | 	defer this.Unlock() | ||||||
| 	this.cache = make(map[string]interface{}) | 	this.cache = make(map[string]interface{}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ package common | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"sync" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func NewBool(t bool) *bool { | func NewBool(t bool) *bool { | ||||||
| @ -67,30 +66,3 @@ func PrettyPrint(json_dirty []byte) []byte { | |||||||
| 	json_pretty.Write([]byte("\n")) | 	json_pretty.Write([]byte("\n")) | ||||||
| 	return json_pretty.Bytes() | 	return json_pretty.Bytes() | ||||||
| } | } | ||||||
|  |  | ||||||
| type SafeMapStringString struct { |  | ||||||
| 	sync.RWMutex |  | ||||||
| 	internal map[string]string |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func NewSafeMapStringString() SafeMapStringString { |  | ||||||
| 	return SafeMapStringString{ |  | ||||||
| 		internal: make(map[string]string), |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func(this SafeMapStringString) Set(key string, value string) { |  | ||||||
| 	this.Lock() |  | ||||||
| 	this.internal[key] = value |  | ||||||
| 	this.Unlock() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func(this SafeMapStringString) Gets(keys ...string) []string{ |  | ||||||
| 	this.RLock() |  | ||||||
| 	res := make([]string, len(keys)) |  | ||||||
|     for i, key := range keys { |  | ||||||
| 		res[i] = this.internal[key] |  | ||||||
|     } |  | ||||||
| 	this.RUnlock() |  | ||||||
| 	return res |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -11,8 +11,6 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ETAGS     SafeMapStringString = NewSafeMapStringString() |  | ||||||
|  |  | ||||||
| func StaticHandler(_path string) func(App, http.ResponseWriter, *http.Request) { | func StaticHandler(_path string) func(App, http.ResponseWriter, *http.Request) { | ||||||
| 	return func(ctx App, res http.ResponseWriter, req *http.Request) { | 	return func(ctx App, res http.ResponseWriter, req *http.Request) { | ||||||
| 		var base string = GetAbsolutePath(_path) | 		var base string = GetAbsolutePath(_path) | ||||||
| @ -95,16 +93,15 @@ func hashFile (path string, n int) string { | |||||||
|  |  | ||||||
| 	stat, err := f.Stat() | 	stat, err := f.Stat() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "UNKNOWN" | 		return "" | ||||||
| 	} | 	} | ||||||
| 	return QuickHash(fmt.Sprintf("%s %d %d %s", path, stat.Size(), stat.Mode(), stat.ModTime()), n) | 	return QuickHash(fmt.Sprintf("%s %d %d %s", path, stat.Size(), stat.Mode(), stat.ModTime()), n) | ||||||
| } | } | ||||||
|  |  | ||||||
| func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) { | func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) { | ||||||
| 	zFilePath := filePath + ".gz" | 	zFilePath := filePath + ".gz" | ||||||
| 	tags := ETAGS.Gets(filePath, zFilePath) | 	etagNormal := hashFile(filePath, 10) | ||||||
| 	etagNormal := tags[0] | 	etagGzip := hashFile(zFilePath, 10) | ||||||
| 	etagGzip := tags[1] |  | ||||||
|  |  | ||||||
| 	if req.Header.Get("If-None-Match") != "" { | 	if req.Header.Get("If-None-Match") != "" { | ||||||
| 		browserTag := req.Header.Get("If-None-Match") | 		browserTag := req.Header.Get("If-None-Match") | ||||||
| @ -120,13 +117,7 @@ func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) { | |||||||
| 	if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { | 	if strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") { | ||||||
| 		if file, err := os.OpenFile(zFilePath, os.O_RDONLY, os.ModePerm); err == nil { | 		if file, err := os.OpenFile(zFilePath, os.O_RDONLY, os.ModePerm); err == nil { | ||||||
| 			head.Set("Content-Encoding", "gzip") | 			head.Set("Content-Encoding", "gzip") | ||||||
| 			if etagGzip == "" { |  | ||||||
| 				tag := hashFile(zFilePath, 10) |  | ||||||
| 				ETAGS.Set(zFilePath, tag) |  | ||||||
| 				head.Set("Etag", tag) |  | ||||||
| 			} else { |  | ||||||
| 			head.Set("Etag", etagGzip) | 			head.Set("Etag", etagGzip) | ||||||
| 			} |  | ||||||
| 			io.Copy(res, file) | 			io.Copy(res, file) | ||||||
| 			file.Close() | 			file.Close() | ||||||
| 			return | 			return | ||||||
| @ -138,13 +129,7 @@ func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) { | |||||||
| 		http.NotFound(res, req) | 		http.NotFound(res, req) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	if etagNormal == "" { |  | ||||||
| 		tag := hashFile(filePath, 10) |  | ||||||
| 		ETAGS.Set(filePath, tag) |  | ||||||
| 		head.Set("Etag", tag) |  | ||||||
| 	} else { |  | ||||||
| 	head.Set("Etag", etagNormal) | 	head.Set("Etag", etagNormal) | ||||||
| 	} |  | ||||||
| 	io.Copy(res, file) | 	io.Copy(res, file) | ||||||
| 	file.Close() | 	file.Close() | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,6 +23,9 @@ func NewBackend(ctx *App, conn map[string]string) (IBackend, error) { | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			if val, ok := d["path"]; ok == true { | 			if val, ok := d["path"]; ok == true { | ||||||
|  | 				if val == nil { | ||||||
|  | 					val = "/" | ||||||
|  | 				} | ||||||
| 				if val != conn["path"] { | 				if val != conn["path"] { | ||||||
| 					continue | 					continue | ||||||
| 				} | 				} | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Mickael KERJEAN
					Mickael KERJEAN