optimize code and add hook gin action and set noroute

This commit is contained in:
xing 2024-04-18 01:39:36 +08:00
parent 5eaf798a6c
commit 166bb08ed0
7 changed files with 195 additions and 127 deletions

View File

@ -8,6 +8,8 @@ import (
"github.com/fthvgb1/wp-go/app/theme" "github.com/fthvgb1/wp-go/app/theme"
"github.com/fthvgb1/wp-go/app/wpconfig" "github.com/fthvgb1/wp-go/app/wpconfig"
"github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/gin-contrib/gzip" "github.com/gin-contrib/gzip"
"github.com/gin-contrib/pprof" "github.com/gin-contrib/pprof"
@ -16,11 +18,27 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
var hooker []func(r *gin.Engine) type GinHook func(*gin.Engine)
// Hook 方便插件在init时使用 var hookers mockmap.Map[string, GinHook]
func Hook(fn ...func(r *gin.Engine)) {
hooker = append(hooker, fn...) // SetGinAction 方便插件在init时使用
func SetGinAction(name string, hook GinHook, orders ...float64) {
hookers.Set(name, hook, orders...)
}
func HookGinAction(name string, fn func(item mockmap.Item[string, GinHook]) mockmap.Item[string, GinHook]) {
item := hookers.Get(name)
if item.Name == "" {
return
}
t := fn(item)
SetGinAction(name, t.Value, t.Order)
}
// DelGinAction 方便插件在init时使用
func DelGinAction(name string) {
hookers.Del(name)
} }
func SetupRouter() *gin.Engine { func SetupRouter() *gin.Engine {
@ -28,16 +46,27 @@ func SetupRouter() *gin.Engine {
// gin.DisableConsoleColor() // gin.DisableConsoleColor()
r := gin.New() r := gin.New()
c := config.GetConfig() c := config.GetConfig()
SetGinAction("initTrustIp", func(r *gin.Engine) {
if len(c.TrustIps) > 0 { if len(c.TrustIps) > 0 {
err := r.SetTrustedProxies(c.TrustIps) err := r.SetTrustedProxies(c.TrustIps)
if err != nil { if err != nil {
panic(err) panic(err)
} }
} }
}, 99.5)
SetGinAction("setTemplate", func(r *gin.Engine) {
r.HTMLRender = theme.BuildTemplate() r.HTMLRender = theme.BuildTemplate()
wpconfig.SetTemplateFs(theme.TemplateFs) wpconfig.SetTemplateFs(theme.TemplateFs)
}, 90.5)
siteFlowLimitMiddleware, siteFlow := middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime) siteFlowLimitMiddleware, siteFlow := middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
reload.Append(func() {
c = config.GetConfig()
siteFlow(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
}, "site-flowLimit-config")
SetGinAction("setGlobalMiddleware", func(r *gin.Engine) {
r.Use( r.Use(
gin.Logger(), gin.Logger(),
middleware.ValidateServerNames(), middleware.ValidateServerNames(),
@ -45,13 +74,18 @@ func SetupRouter() *gin.Engine {
siteFlowLimitMiddleware, siteFlowLimitMiddleware,
middleware.SetStaticFileCache, middleware.SetStaticFileCache,
) )
}, 88.5)
SetGinAction("setGzip", func(r *gin.Engine) {
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用 //gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
if c.Gzip { if c.Gzip {
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{ r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
"/wp-includes/", "/wp-content/", "/wp-includes/", "/wp-content/",
}))) })))
} }
}, 87.6)
SetGinAction("setWpDir", func(r *gin.Engine) {
if c.WpDir == "" { if c.WpDir == "" {
panic("wordpress path can't be empty") panic("wordpress path can't be empty")
} }
@ -61,9 +95,14 @@ func SetupRouter() *gin.Engine {
r.Static("/wp-includes/css", str.Join(c.WpDir, "/wp-includes/css")) r.Static("/wp-includes/css", str.Join(c.WpDir, "/wp-includes/css"))
r.Static("/wp-includes/fonts", str.Join(c.WpDir, "/wp-includes/fonts")) r.Static("/wp-includes/fonts", str.Join(c.WpDir, "/wp-includes/fonts"))
r.Static("/wp-includes/js", str.Join(c.WpDir, "/wp-includes/js")) r.Static("/wp-includes/js", str.Join(c.WpDir, "/wp-includes/js"))
}, 86.1)
SetGinAction("setSession", func(r *gin.Engine) {
store := cookie.NewStore([]byte("secret")) store := cookie.NewStore([]byte("secret"))
r.Use(sessions.Sessions("go-wp", store)) r.Use(sessions.Sessions("go-wp", store))
}, 85.1)
SetGinAction("setRoute", func(r *gin.Engine) {
r.GET("/", actions.Feed, middleware.SearchLimit(c.SingleIpSearchNum), r.GET("/", actions.Feed, middleware.SearchLimit(c.SingleIpSearchNum),
actions.ThemeHook(constraints.Home)) actions.ThemeHook(constraints.Home))
r.GET("/page/:page", actions.ThemeHook(constraints.Home)) r.GET("/page/:page", actions.ThemeHook(constraints.Home))
@ -81,19 +120,25 @@ func SetupRouter() *gin.Engine {
r.GET("/p/:id/feed", actions.PostFeed) r.GET("/p/:id/feed", actions.PostFeed)
r.GET("/feed", actions.SiteFeed) r.GET("/feed", actions.SiteFeed)
r.GET("/comments/feed", actions.CommentsFeed) r.GET("/comments/feed", actions.CommentsFeed)
//r.NoRoute(actions.ThemeHook(constraints.NoRoute))
commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime) commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime)
r.POST("/comment", commentMiddleWare, actions.PostComment) r.POST("/comment", commentMiddleWare, actions.PostComment)
r.NoRoute(actions.ThemeHook(constraints.NoRoute))
}, 84.6)
SetGinAction("setpprof", func(r *gin.Engine) {
if c.Pprof != "" { if c.Pprof != "" {
pprof.Register(r, c.Pprof) pprof.Register(r, c.Pprof)
} }
for _, fn := range hooker { }, 80.8)
fn(r)
slice.SimpleSort(hookers, slice.DESC, func(t mockmap.Item[string, GinHook]) float64 {
return t.Order
})
for _, fn := range hookers {
fn.Value(r)
} }
reload.Append(func() {
c := config.GetConfig()
siteFlow(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
}, "site-flowLimit-config")
return r return r
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/fthvgb1/wp-go/app/pkg/constraints" "github.com/fthvgb1/wp-go/app/pkg/constraints"
"github.com/fthvgb1/wp-go/app/theme/wp" "github.com/fthvgb1/wp-go/app/theme/wp"
"github.com/fthvgb1/wp-go/app/theme/wp/components/widget" "github.com/fthvgb1/wp-go/app/theme/wp/components/widget"
"github.com/fthvgb1/wp-go/app/theme/wp/route"
"github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper/maps" "github.com/fthvgb1/wp-go/helper/maps"
"github.com/fthvgb1/wp-go/helper/number" "github.com/fthvgb1/wp-go/helper/number"
@ -160,4 +161,7 @@ func CommonMiddleware(h *wp.Handle) {
h.PushHandler(constraints.PipeMiddleware, constraints.Detail, h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
wp.NewHandleFn(ShowPreComment, 100, "middleware.ShowPreComment"), wp.NewHandleFn(ShowPreComment, 100, "middleware.ShowPreComment"),
) )
h.PushHandler(constraints.PipeMiddleware, constraints.NoRoute,
wp.NewHandleFn(route.ResolveRoute, 100, "route.ResolveRoute"),
)
} }

View File

@ -5,9 +5,12 @@ import (
"github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"net/http"
"regexp" "regexp"
) )
// Route
// Type value equal const or reg
type Route struct { type Route struct {
Path string Path string
Scene string Scene string
@ -131,4 +134,6 @@ func ResolveRoute(h *wp.Handle) {
return return
} }
} }
h.C.Status(http.StatusNotFound)
h.Abort()
} }

View File

@ -5,7 +5,7 @@ import (
"github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/cache/reload" "github.com/fthvgb1/wp-go/cache/reload"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice" "github.com/fthvgb1/wp-go/helper/slice/mockmap"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"runtime" "runtime"
@ -15,52 +15,20 @@ import (
var mutex sync.Mutex var mutex sync.Mutex
type Queue struct { type Fn func(context.Context)
Name string
Fn func(context.Context)
}
type Queues []Queue
func (q *Queues) Get(name string) Queue {
_, v := slice.SearchFirst(*q, func(t Queue) bool {
return name == t.Name
})
return v
}
func (q *Queues) Set(name string, fn func(context.Context)) {
i := slice.IndexOfBy(*q, func(t Queue) bool {
return name == t.Name
})
if i > -1 {
(*q)[i].Fn = fn
return
}
*q = append(*q, Queue{name, fn})
}
func (q *Queues) Del(name string) {
i := slice.IndexOfBy(*q, func(t Queue) bool {
return name == t.Name
})
if i > -1 {
slice.Delete((*[]Queue)(q), i)
}
}
type clearExpired interface { type clearExpired interface {
ClearExpired(ctx context.Context) ClearExpired(ctx context.Context)
} }
var clears = safety.NewVar(Queues{}) var clears = safety.NewVar(mockmap.Map[string, Fn]{})
var flushes = safety.NewVar(Queues{}) var flushes = safety.NewVar(mockmap.Map[string, Fn]{})
func Flush() { func Flush() {
ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn") ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn")
for _, f := range flushes.Load() { for _, f := range flushes.Load() {
f.Fn(ctx) f.Value(ctx)
} }
} }
@ -68,12 +36,12 @@ func Flushes(ctx context.Context, names ...string) {
execute(ctx, flushes, names...) execute(ctx, flushes, names...)
} }
func execute(ctx context.Context, q *safety.Var[Queues], names ...string) { func execute(ctx context.Context, q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
queues := q.Load() queues := q.Load()
for _, name := range names { for _, name := range names {
queue := queues.Get(name) queue := queues.Get(name)
if queue.Fn != nil { if queue.Value != nil {
queue.Fn(ctx) queue.Value(ctx)
} }
} }
} }
@ -118,9 +86,9 @@ func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
} else { } else {
lo := cache.NewLocks[K](loFn) lo := cache.NewLocks[K](loFn)
lockFn = lo.GetLock lockFn = lo.GetLock
PushOrSetFlush(Queue{ PushOrSetFlush(mockmap.Item[string, Fn]{
Name: name, Name: name,
Fn: lo.Flush, Value: lo.Flush,
}) })
} }
@ -141,14 +109,14 @@ func ChangeExpireTime(t time.Duration, coverConf bool, name ...string) {
reload.SetFnVal(s, t, coverConf) reload.SetFnVal(s, t, coverConf)
} }
} }
func pushOrSet(q *safety.Var[Queues], queues ...Queue) { func pushOrSet(q *safety.Var[mockmap.Map[string, Fn]], queues ...mockmap.Item[string, Fn]) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
qu := q.Load() qu := q.Load()
for _, queue := range queues { for _, queue := range queues {
v := qu.Get(queue.Name) v := qu.Get(queue.Name)
if v.Fn != nil { if v.Value != nil {
qu.Set(queue.Name, queue.Fn) qu.Set(queue.Name, queue.Value)
} else { } else {
qu = append(qu, queue) qu = append(qu, queue)
} }
@ -157,16 +125,16 @@ func pushOrSet(q *safety.Var[Queues], queues ...Queue) {
} }
// PushOrSetFlush will execute flush func when call Flush or Flushes // PushOrSetFlush will execute flush func when call Flush or Flushes
func PushOrSetFlush(queues ...Queue) { func PushOrSetFlush(queues ...mockmap.Item[string, Fn]) {
pushOrSet(flushes, queues...) pushOrSet(flushes, queues...)
} }
// PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds // PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds
func PushOrSetClearExpired(queues ...Queue) { func PushOrSetClearExpired(queues ...mockmap.Item[string, Fn]) {
pushOrSet(clears, queues...) pushOrSet(clears, queues...)
} }
func del(q *safety.Var[Queues], names ...string) { func del(q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
queues := q.Load() queues := q.Load()
@ -190,6 +158,6 @@ func ClearExpireds(ctx context.Context, names ...string) {
func ClearExpired() { func ClearExpired() {
ctx := context.WithValue(context.Background(), "execClearExpired", "mangerClearExpiredFn") ctx := context.WithValue(context.Background(), "execClearExpired", "mangerClearExpiredFn")
for _, queue := range clears.Load() { for _, queue := range clears.Load() {
queue.Fn(ctx) queue.Value(ctx)
} }
} }

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"time" "time"
@ -110,13 +111,13 @@ func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapB
if name != "" { if name != "" {
PushMangerMap(name, m) PushMangerMap(name, m)
} }
PushOrSetFlush(Queue{ PushOrSetFlush(mockmap.Item[string, Fn]{
Name: name, Name: name,
Fn: m.Flush, Value: m.Flush,
}) })
PushOrSetClearExpired(Queue{ PushOrSetClearExpired(mockmap.Item[string, Fn]{
Name: name, Name: name,
Fn: m.ClearExpired, Value: m.ClearExpired,
}) })
if f != nil && name != "" { if f != nil && name != "" {
SetExpireTime(any(data).(cache.SetTime), name, 0, f) SetExpireTime(any(data).(cache.SetTime), name, 0, f)

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"github.com/fthvgb1/wp-go/cache" "github.com/fthvgb1/wp-go/cache"
"github.com/fthvgb1/wp-go/helper" "github.com/fthvgb1/wp-go/helper"
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
str "github.com/fthvgb1/wp-go/helper/strings" str "github.com/fthvgb1/wp-go/helper/strings"
"github.com/fthvgb1/wp-go/safety" "github.com/fthvgb1/wp-go/safety"
"time" "time"
@ -35,15 +36,15 @@ func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T
if name != "" { if name != "" {
varCache.Store(name, v) varCache.Store(name, v)
} }
PushOrSetFlush(Queue{ PushOrSetFlush(mockmap.Item[string, Fn]{
Name: name, Name: name,
Fn: v.Flush, Value: v.Flush,
}) })
cc, ok := any(c).(clearExpired) cc, ok := any(c).(clearExpired)
if ok { if ok {
PushOrSetClearExpired(Queue{ PushOrSetClearExpired(mockmap.Item[string, Fn]{
Name: name, Name: name,
Fn: cc.ClearExpired, Value: cc.ClearExpired,
}) })
} }
return v return v

View File

@ -0,0 +1,44 @@
package mockmap
import (
"github.com/fthvgb1/wp-go/helper/slice"
)
type Item[K comparable, T any] struct {
Name K
Value T
Order float64
}
type Map[K comparable, T any] []Item[K, T]
func (q *Map[K, T]) Get(name K) Item[K, T] {
_, v := slice.SearchFirst(*q, func(t Item[K, T]) bool {
return name == t.Name
})
return v
}
func (q *Map[K, T]) Set(name K, value T, orders ...float64) {
i := slice.IndexOfBy(*q, func(t Item[K, T]) bool {
return name == t.Name
})
if i > -1 {
(*q)[i].Value = value
return
}
order := float64(0)
if len(orders) > 0 {
order = orders[0]
}
*q = append(*q, Item[K, T]{name, value, order})
}
func (q *Map[K, T]) Del(name K) {
i := slice.IndexOfBy(*q, func(t Item[K, T]) bool {
return name == t.Name
})
if i > -1 {
slice.Delete((*[]Item[K, T])(q), i)
}
}