Compare commits

...

3 Commits
v0.1.3 ... main

Author SHA1 Message Date
fcl a30d5783ae 修复静态资源访问错误的问题 2025-08-18 10:43:10 +08:00
Yavolte bfc15136fd 修改支持文件压缩逻辑 2025-08-18 10:17:43 +08:00
Yavolte b35a655414 update map 2025-08-12 11:33:53 +08:00
2 changed files with 59 additions and 28 deletions

View File

@ -2,15 +2,15 @@ package maps
import "sync" import "sync"
type GenericMap[K comparable, V any] struct { type Map[K comparable, V any] struct {
m sync.Map m *sync.Map
} }
func (gm *GenericMap[K, V]) Store(key K, value V) { func (gm *Map[K, V]) Store(key K, value V) {
gm.m.Store(key, value) gm.m.Store(key, value)
} }
func (gm *GenericMap[K, V]) Load(key K) (V, bool) { func (gm *Map[K, V]) Load(key K) (V, bool) {
value, ok := gm.m.Load(key) value, ok := gm.m.Load(key)
if !ok { if !ok {
var zero V var zero V
@ -19,39 +19,54 @@ func (gm *GenericMap[K, V]) Load(key K) (V, bool) {
return value.(V), true return value.(V), true
} }
func (gm *GenericMap[K, V]) Delete(key K) { func (gm *Map[K, V]) Delete(key K) {
gm.m.Delete(key) gm.m.Delete(key)
} }
func (gm *GenericMap[K, V]) Range(f func(key K, value V) bool) { func (gm *Map[K, V]) Range(f func(key K, value V) bool) {
gm.m.Range(func(key, value any) bool { gm.m.Range(func(key, value any) bool {
return f(key.(K), value.(V)) return f(key.(K), value.(V))
}) })
} }
func (gm *GenericMap[K, V]) Swap(key K, value V) (previous V, loaded bool) { func (gm *Map[K, V]) Swap(key K, value V) (previous V, loaded bool) {
actual, swapped := gm.m.Swap(key, value) actual, swapped := gm.m.Swap(key, value)
return actual.(V), swapped return actual.(V), swapped
} }
func (gm *GenericMap[K, V]) LoadOrStore(key K, value V) (V, bool) { func (gm *Map[K, V]) Len() int {
var n int
gm.m.Range(func(key, value any) bool {
n++
return true
})
return n
}
func (gm *Map[K, V]) Clear() {
gm.m.Clear()
}
func (gm *Map[K, V]) LoadOrStore(key K, value V) (V, bool) {
actual, loaded := gm.m.LoadOrStore(key, value) actual, loaded := gm.m.LoadOrStore(key, value)
return actual.(V), loaded return actual.(V), loaded
} }
func (gm *GenericMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) { func (gm *Map[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
actual, loaded := gm.m.LoadAndDelete(key) actual, loaded := gm.m.LoadAndDelete(key)
return actual.(V), loaded return actual.(V), loaded
} }
func (gm *GenericMap[K, V]) CompareAndSwap(key K, old V, new V) (swapped bool) { func (gm *Map[K, V]) CompareAndSwap(key K, old V, new V) (swapped bool) {
return gm.m.CompareAndSwap(key, old, new) return gm.m.CompareAndSwap(key, old, new)
} }
func (gm *GenericMap[K, V]) CompareAndDelete(key K, old V) (deleted bool) { func (gm *Map[K, V]) CompareAndDelete(key K, old V) (deleted bool) {
return gm.m.CompareAndDelete(key, old) return gm.m.CompareAndDelete(key, old)
} }
func New[K comparable, V any]() *GenericMap[K, V] { func New[K comparable, V any]() *Map[K, V] {
return &GenericMap[K, V]{m: sync.Map{}} return &Map[K, V]{
m: new(sync.Map),
}
} }

View File

@ -37,6 +37,7 @@ type Server struct {
fs *filesystem fs *filesystem
middlewares []middleware.Middleware middlewares []middleware.Middleware
Logger logger.Logger Logger logger.Logger
autoCompress bool
} }
func (s *Server) Endpoint(ctx context.Context) (string, error) { func (s *Server) Endpoint(ctx context.Context) (string, error) {
@ -104,7 +105,8 @@ func (s *Server) Handle(method string, uri string, handler http.HandlerFunc) {
}) })
} }
func (s *Server) Webroot(prefix string, fs http.FileSystem) { func (s *Server) Webroot(prefix string, authCompress bool, fs http.FileSystem) {
s.autoCompress = authCompress
s.fs = newFS(time.Now(), fs) s.fs = newFS(time.Now(), fs)
s.fs.SetPrefix(prefix) s.fs.SetPrefix(prefix)
s.fs.DenyAccessDirectory() s.fs.DenyAccessDirectory()
@ -112,6 +114,9 @@ func (s *Server) Webroot(prefix string, fs http.FileSystem) {
} }
func (s *Server) shouldCompress(req *http.Request) bool { func (s *Server) shouldCompress(req *http.Request) bool {
if !s.autoCompress {
return false
}
if !strings.Contains(req.Header.Get(headerAcceptEncoding), "gzip") || if !strings.Contains(req.Header.Get(headerAcceptEncoding), "gzip") ||
strings.Contains(req.Header.Get("Connection"), "Upgrade") { strings.Contains(req.Header.Get("Connection"), "Upgrade") {
return false return false
@ -125,11 +130,11 @@ func (s *Server) shouldCompress(req *http.Request) bool {
return false return false
} }
func (s *Server) staticHandle(ctx *gin.Context, fp http.File) { func (s *Server) staticHandle(ctx *gin.Context, fp http.File) bool {
uri := path.Clean(ctx.Request.URL.Path) uri := path.Clean(ctx.Request.URL.Path)
fi, err := fp.Stat() fi, err := fp.Stat()
if err != nil { if err != nil {
return return false
} }
if !fi.IsDir() { if !fi.IsDir() {
//https://github.com/gin-contrib/gzip //https://github.com/gin-contrib/gzip
@ -157,14 +162,25 @@ func (s *Server) staticHandle(ctx *gin.Context, fp http.File) {
} }
http.ServeContent(ctx.Writer, ctx.Request, path.Base(uri), s.fs.modtime, fp) http.ServeContent(ctx.Writer, ctx.Request, path.Base(uri), s.fs.modtime, fp)
ctx.Abort() ctx.Abort()
return true
} }
func (s *Server) notFoundHandle(ctx *gin.Context) { func (s *Server) notFoundHandle(ctx *gin.Context) {
if s.fs != nil && ctx.Request.Method == http.MethodGet { if s.fs != nil && ctx.Request.Method == http.MethodGet {
uri := path.Clean(ctx.Request.URL.Path) uri := path.Clean(ctx.Request.URL.Path)
if fp, err := s.fs.Open(uri); err == nil { if fp, err := s.fs.Open(uri); err == nil {
s.staticHandle(ctx, fp) defer fp.Close()
fp.Close() if s.staticHandle(ctx, fp) {
return
}
} else {
//if found compress file
if fp, err := s.fs.Open(uri + ".gz"); err == nil {
defer fp.Close()
if s.staticHandle(ctx, fp) {
return
}
}
} }
} }
ctx.JSON(http.StatusNotFound, newResponse(errors.NotFound, "Not Found", nil)) ctx.JSON(http.StatusNotFound, newResponse(errors.NotFound, "Not Found", nil))