fix: json store marshaling, api handler

- code clean up
- uncomment and simplify api auth handler
- fix redirect url for frontend
- proper redirect
This commit is contained in:
yusing
2025-04-24 04:47:42 +08:00
parent b815c6fd69
commit 7461344004
14 changed files with 234 additions and 213 deletions

View File

@@ -1,47 +1,95 @@
package jsonstore
import (
"encoding/json"
"path/filepath"
"sync"
"github.com/puzpuzpuz/xsync/v3"
"github.com/yusing/go-proxy/internal/common"
"github.com/yusing/go-proxy/internal/gperr"
"github.com/yusing/go-proxy/internal/logging"
"github.com/yusing/go-proxy/internal/task"
"github.com/yusing/go-proxy/internal/utils"
)
type JSONStore[VT any] struct{ m jsonStoreInternal }
type namespace string
func NewStore[VT any](namespace namespace) JSONStore[VT] {
storesMu.Lock()
defer storesMu.Unlock()
if s, ok := stores[namespace]; ok {
return JSONStore[VT]{s}
type Typed[VT any] struct {
*xsync.MapOf[string, VT]
}
type storesMap struct {
sync.RWMutex
m map[namespace]any
}
var stores = storesMap{m: make(map[namespace]any)}
var storesPath = common.DataDir
func init() {
if err := load(); err != nil {
logging.Error().Err(err).Msg("failed to load stores")
}
m := jsonStoreInternal{xsync.NewMapOf[string, any]()}
stores[namespace] = m
return JSONStore[VT]{m}
task.OnProgramExit("save_stores", func() {
if err := save(); err != nil {
logging.Error().Err(err).Msg("failed to save stores")
}
})
}
func (s JSONStore[VT]) Load(key string) (_ VT, _ bool) {
value, ok := s.m.Load(key)
if !ok {
return
}
return value.(VT), true
}
func (s JSONStore[VT]) Has(key string) bool {
_, ok := s.m.Load(key)
return ok
}
func (s JSONStore[VT]) Store(key string, value VT) {
s.m.Store(key, value)
}
func (s JSONStore[VT]) Delete(key string) {
s.m.Delete(key)
}
func (s JSONStore[VT]) Iter(yield func(key string, value VT) bool) {
for k, v := range s.m.Range {
if !yield(k, v.(VT)) {
return
func load() error {
stores.Lock()
defer stores.Unlock()
errs := gperr.NewBuilder("failed to load data stores")
for ns, store := range stores.m {
if err := utils.LoadJSONIfExist(filepath.Join(storesPath, string(ns)+".json"), &store); err != nil {
errs.Add(err)
}
}
return errs.Error()
}
func save() error {
stores.Lock()
defer stores.Unlock()
errs := gperr.NewBuilder("failed to save data stores")
for ns, store := range stores.m {
if err := utils.SaveJSON(filepath.Join(common.DataDir, string(ns)+".json"), &store, 0o644); err != nil {
errs.Add(err)
}
}
return errs.Error()
}
func Store[VT any](namespace namespace) Typed[VT] {
stores.Lock()
defer stores.Unlock()
if s, ok := stores.m[namespace]; ok {
return s.(Typed[VT])
}
m := Typed[VT]{MapOf: xsync.NewMapOf[string, VT]()}
stores.m[namespace] = m
return m
}
func (s Typed[VT]) MarshalJSON() ([]byte, error) {
tmp := make(map[string]VT, s.Size())
for k, v := range s.Range {
tmp[k] = v
}
return json.Marshal(tmp)
}
func (s Typed[VT]) UnmarshalJSON(data []byte) error {
tmp := make(map[string]VT)
if err := json.Unmarshal(data, &tmp); err != nil {
return err
}
s.MapOf = xsync.NewMapOf[string, VT](xsync.WithPresize(len(tmp)))
for k, v := range tmp {
s.MapOf.Store(k, v)
}
return nil
}