optimize code and add hook gin action and set noroute
This commit is contained in:
parent
5eaf798a6c
commit
166bb08ed0
|
@ -8,6 +8,8 @@ import (
|
|||
"github.com/fthvgb1/wp-go/app/theme"
|
||||
"github.com/fthvgb1/wp-go/app/wpconfig"
|
||||
"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"
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-contrib/pprof"
|
||||
|
@ -16,11 +18,27 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var hooker []func(r *gin.Engine)
|
||||
type GinHook func(*gin.Engine)
|
||||
|
||||
// Hook 方便插件在init时使用
|
||||
func Hook(fn ...func(r *gin.Engine)) {
|
||||
hooker = append(hooker, fn...)
|
||||
var hookers mockmap.Map[string, GinHook]
|
||||
|
||||
// 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 {
|
||||
|
@ -28,72 +46,99 @@ func SetupRouter() *gin.Engine {
|
|||
// gin.DisableConsoleColor()
|
||||
r := gin.New()
|
||||
c := config.GetConfig()
|
||||
if len(c.TrustIps) > 0 {
|
||||
err := r.SetTrustedProxies(c.TrustIps)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
SetGinAction("initTrustIp", func(r *gin.Engine) {
|
||||
if len(c.TrustIps) > 0 {
|
||||
err := r.SetTrustedProxies(c.TrustIps)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 99.5)
|
||||
|
||||
SetGinAction("setTemplate", func(r *gin.Engine) {
|
||||
r.HTMLRender = theme.BuildTemplate()
|
||||
wpconfig.SetTemplateFs(theme.TemplateFs)
|
||||
}, 90.5)
|
||||
|
||||
r.HTMLRender = theme.BuildTemplate()
|
||||
wpconfig.SetTemplateFs(theme.TemplateFs)
|
||||
siteFlowLimitMiddleware, siteFlow := middleware.FlowLimit(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
||||
r.Use(
|
||||
gin.Logger(),
|
||||
middleware.ValidateServerNames(),
|
||||
middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
|
||||
siteFlowLimitMiddleware,
|
||||
middleware.SetStaticFileCache,
|
||||
)
|
||||
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
|
||||
if c.Gzip {
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
|
||||
"/wp-includes/", "/wp-content/",
|
||||
})))
|
||||
}
|
||||
|
||||
if c.WpDir == "" {
|
||||
panic("wordpress path can't be empty")
|
||||
}
|
||||
r.Static("/wp-content/uploads", str.Join(c.WpDir, "/wp-content/uploads"))
|
||||
r.Static("/wp-content/themes", str.Join(c.WpDir, "/wp-content/themes"))
|
||||
r.Static("/wp-content/plugins", str.Join(c.WpDir, "/wp-content/plugins"))
|
||||
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/js", str.Join(c.WpDir, "/wp-includes/js"))
|
||||
|
||||
store := cookie.NewStore([]byte("secret"))
|
||||
r.Use(sessions.Sessions("go-wp", store))
|
||||
r.GET("/", actions.Feed, middleware.SearchLimit(c.SingleIpSearchNum),
|
||||
actions.ThemeHook(constraints.Home))
|
||||
r.GET("/page/:page", actions.ThemeHook(constraints.Home))
|
||||
r.GET("/p/category/:category", actions.ThemeHook(constraints.Category))
|
||||
r.GET("/p/category/:category/page/:page", actions.ThemeHook(constraints.Category))
|
||||
r.GET("/p/tag/:tag", actions.ThemeHook(constraints.Tag))
|
||||
r.GET("/p/tag/:tag/page/:page", actions.ThemeHook(constraints.Tag))
|
||||
r.GET("/p/date/:year/:month", actions.ThemeHook(constraints.Archive))
|
||||
r.GET("/p/date/:year/:month/page/:page", actions.ThemeHook(constraints.Archive))
|
||||
r.GET("/p/author/:author", actions.ThemeHook(constraints.Author))
|
||||
r.GET("/p/author/:author/page/:page", actions.ThemeHook(constraints.Author))
|
||||
r.POST("/login", actions.Login)
|
||||
r.GET("/p/:id", actions.ThemeHook(constraints.Detail))
|
||||
r.GET("/p/:id/comment-page-:page", actions.ThemeHook(constraints.Detail))
|
||||
r.GET("/p/:id/feed", actions.PostFeed)
|
||||
r.GET("/feed", actions.SiteFeed)
|
||||
r.GET("/comments/feed", actions.CommentsFeed)
|
||||
//r.NoRoute(actions.ThemeHook(constraints.NoRoute))
|
||||
commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime)
|
||||
r.POST("/comment", commentMiddleWare, actions.PostComment)
|
||||
if c.Pprof != "" {
|
||||
pprof.Register(r, c.Pprof)
|
||||
}
|
||||
for _, fn := range hooker {
|
||||
fn(r)
|
||||
}
|
||||
|
||||
reload.Append(func() {
|
||||
c := config.GetConfig()
|
||||
c = config.GetConfig()
|
||||
siteFlow(c.MaxRequestSleepNum, c.MaxRequestNum, c.CacheTime.SleepTime)
|
||||
}, "site-flowLimit-config")
|
||||
|
||||
SetGinAction("setGlobalMiddleware", func(r *gin.Engine) {
|
||||
r.Use(
|
||||
gin.Logger(),
|
||||
middleware.ValidateServerNames(),
|
||||
middleware.RecoverAndSendMail(gin.DefaultErrorWriter),
|
||||
siteFlowLimitMiddleware,
|
||||
middleware.SetStaticFileCache,
|
||||
)
|
||||
}, 88.5)
|
||||
|
||||
SetGinAction("setGzip", func(r *gin.Engine) {
|
||||
//gzip 因为一般会用nginx做反代时自动使用gzip,所以go这边本身可以不用
|
||||
if c.Gzip {
|
||||
r.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedPaths([]string{
|
||||
"/wp-includes/", "/wp-content/",
|
||||
})))
|
||||
}
|
||||
}, 87.6)
|
||||
|
||||
SetGinAction("setWpDir", func(r *gin.Engine) {
|
||||
if c.WpDir == "" {
|
||||
panic("wordpress path can't be empty")
|
||||
}
|
||||
r.Static("/wp-content/uploads", str.Join(c.WpDir, "/wp-content/uploads"))
|
||||
r.Static("/wp-content/themes", str.Join(c.WpDir, "/wp-content/themes"))
|
||||
r.Static("/wp-content/plugins", str.Join(c.WpDir, "/wp-content/plugins"))
|
||||
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/js", str.Join(c.WpDir, "/wp-includes/js"))
|
||||
}, 86.1)
|
||||
|
||||
SetGinAction("setSession", func(r *gin.Engine) {
|
||||
store := cookie.NewStore([]byte("secret"))
|
||||
r.Use(sessions.Sessions("go-wp", store))
|
||||
}, 85.1)
|
||||
|
||||
SetGinAction("setRoute", func(r *gin.Engine) {
|
||||
r.GET("/", actions.Feed, middleware.SearchLimit(c.SingleIpSearchNum),
|
||||
actions.ThemeHook(constraints.Home))
|
||||
r.GET("/page/:page", actions.ThemeHook(constraints.Home))
|
||||
r.GET("/p/category/:category", actions.ThemeHook(constraints.Category))
|
||||
r.GET("/p/category/:category/page/:page", actions.ThemeHook(constraints.Category))
|
||||
r.GET("/p/tag/:tag", actions.ThemeHook(constraints.Tag))
|
||||
r.GET("/p/tag/:tag/page/:page", actions.ThemeHook(constraints.Tag))
|
||||
r.GET("/p/date/:year/:month", actions.ThemeHook(constraints.Archive))
|
||||
r.GET("/p/date/:year/:month/page/:page", actions.ThemeHook(constraints.Archive))
|
||||
r.GET("/p/author/:author", actions.ThemeHook(constraints.Author))
|
||||
r.GET("/p/author/:author/page/:page", actions.ThemeHook(constraints.Author))
|
||||
r.POST("/login", actions.Login)
|
||||
r.GET("/p/:id", actions.ThemeHook(constraints.Detail))
|
||||
r.GET("/p/:id/comment-page-:page", actions.ThemeHook(constraints.Detail))
|
||||
r.GET("/p/:id/feed", actions.PostFeed)
|
||||
r.GET("/feed", actions.SiteFeed)
|
||||
r.GET("/comments/feed", actions.CommentsFeed)
|
||||
commentMiddleWare, _ := middleware.FlowLimit(c.MaxRequestSleepNum, 5, c.CacheTime.SleepTime)
|
||||
r.POST("/comment", commentMiddleWare, actions.PostComment)
|
||||
|
||||
r.NoRoute(actions.ThemeHook(constraints.NoRoute))
|
||||
}, 84.6)
|
||||
|
||||
SetGinAction("setpprof", func(r *gin.Engine) {
|
||||
if c.Pprof != "" {
|
||||
pprof.Register(r, c.Pprof)
|
||||
}
|
||||
}, 80.8)
|
||||
|
||||
slice.SimpleSort(hookers, slice.DESC, func(t mockmap.Item[string, GinHook]) float64 {
|
||||
return t.Order
|
||||
})
|
||||
|
||||
for _, fn := range hookers {
|
||||
fn.Value(r)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"github.com/fthvgb1/wp-go/app/pkg/constraints"
|
||||
"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/route"
|
||||
"github.com/fthvgb1/wp-go/cache/reload"
|
||||
"github.com/fthvgb1/wp-go/helper/maps"
|
||||
"github.com/fthvgb1/wp-go/helper/number"
|
||||
|
@ -160,4 +161,7 @@ func CommonMiddleware(h *wp.Handle) {
|
|||
h.PushHandler(constraints.PipeMiddleware, constraints.Detail,
|
||||
wp.NewHandleFn(ShowPreComment, 100, "middleware.ShowPreComment"),
|
||||
)
|
||||
h.PushHandler(constraints.PipeMiddleware, constraints.NoRoute,
|
||||
wp.NewHandleFn(route.ResolveRoute, 100, "route.ResolveRoute"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,9 +5,12 @@ import (
|
|||
"github.com/fthvgb1/wp-go/cache/reload"
|
||||
"github.com/fthvgb1/wp-go/helper/slice"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"net/http"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Route
|
||||
// Type value equal const or reg
|
||||
type Route struct {
|
||||
Path string
|
||||
Scene string
|
||||
|
@ -131,4 +134,6 @@ func ResolveRoute(h *wp.Handle) {
|
|||
return
|
||||
}
|
||||
}
|
||||
h.C.Status(http.StatusNotFound)
|
||||
h.Abort()
|
||||
}
|
||||
|
|
68
cache/cachemanager/manger.go
vendored
68
cache/cachemanager/manger.go
vendored
|
@ -5,7 +5,7 @@ import (
|
|||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/cache/reload"
|
||||
"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"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"runtime"
|
||||
|
@ -15,52 +15,20 @@ import (
|
|||
|
||||
var mutex sync.Mutex
|
||||
|
||||
type Queue struct {
|
||||
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 Fn func(context.Context)
|
||||
|
||||
type clearExpired interface {
|
||||
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() {
|
||||
ctx := context.WithValue(context.Background(), "execFlushBy", "mangerFlushFn")
|
||||
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...)
|
||||
}
|
||||
|
||||
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()
|
||||
for _, name := range names {
|
||||
queue := queues.Get(name)
|
||||
if queue.Fn != nil {
|
||||
queue.Fn(ctx)
|
||||
if queue.Value != nil {
|
||||
queue.Value(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,9 +86,9 @@ func buildLockFn[K comparable](args ...any) cache.LockFn[K] {
|
|||
} else {
|
||||
lo := cache.NewLocks[K](loFn)
|
||||
lockFn = lo.GetLock
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: lo.Flush,
|
||||
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||
Name: name,
|
||||
Value: lo.Flush,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -141,14 +109,14 @@ func ChangeExpireTime(t time.Duration, coverConf bool, name ...string) {
|
|||
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()
|
||||
defer mutex.Unlock()
|
||||
qu := q.Load()
|
||||
for _, queue := range queues {
|
||||
v := qu.Get(queue.Name)
|
||||
if v.Fn != nil {
|
||||
qu.Set(queue.Name, queue.Fn)
|
||||
if v.Value != nil {
|
||||
qu.Set(queue.Name, queue.Value)
|
||||
} else {
|
||||
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
|
||||
func PushOrSetFlush(queues ...Queue) {
|
||||
func PushOrSetFlush(queues ...mockmap.Item[string, Fn]) {
|
||||
pushOrSet(flushes, queues...)
|
||||
}
|
||||
|
||||
// PushOrSetClearExpired will execute clearExpired func when call ClearExpired or ClearExpireds
|
||||
func PushOrSetClearExpired(queues ...Queue) {
|
||||
func PushOrSetClearExpired(queues ...mockmap.Item[string, Fn]) {
|
||||
pushOrSet(clears, queues...)
|
||||
}
|
||||
|
||||
func del(q *safety.Var[Queues], names ...string) {
|
||||
func del(q *safety.Var[mockmap.Map[string, Fn]], names ...string) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
queues := q.Load()
|
||||
|
@ -190,6 +158,6 @@ func ClearExpireds(ctx context.Context, names ...string) {
|
|||
func ClearExpired() {
|
||||
ctx := context.WithValue(context.Background(), "execClearExpired", "mangerClearExpiredFn")
|
||||
for _, queue := range clears.Load() {
|
||||
queue.Fn(ctx)
|
||||
queue.Value(ctx)
|
||||
}
|
||||
}
|
||||
|
|
13
cache/cachemanager/mapcache.go
vendored
13
cache/cachemanager/mapcache.go
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"time"
|
||||
|
@ -110,13 +111,13 @@ func NewMapCache[K comparable, V any](data cache.Cache[K, V], batchFn cache.MapB
|
|||
if name != "" {
|
||||
PushMangerMap(name, m)
|
||||
}
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: m.Flush,
|
||||
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||
Name: name,
|
||||
Value: m.Flush,
|
||||
})
|
||||
PushOrSetClearExpired(Queue{
|
||||
Name: name,
|
||||
Fn: m.ClearExpired,
|
||||
PushOrSetClearExpired(mockmap.Item[string, Fn]{
|
||||
Name: name,
|
||||
Value: m.ClearExpired,
|
||||
})
|
||||
if f != nil && name != "" {
|
||||
SetExpireTime(any(data).(cache.SetTime), name, 0, f)
|
||||
|
|
13
cache/cachemanager/varcache.go
vendored
13
cache/cachemanager/varcache.go
vendored
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"github.com/fthvgb1/wp-go/cache"
|
||||
"github.com/fthvgb1/wp-go/helper"
|
||||
"github.com/fthvgb1/wp-go/helper/slice/mockmap"
|
||||
str "github.com/fthvgb1/wp-go/helper/strings"
|
||||
"github.com/fthvgb1/wp-go/safety"
|
||||
"time"
|
||||
|
@ -35,15 +36,15 @@ func NewVarCache[T any](c cache.AnyCache[T], fn func(context.Context, ...any) (T
|
|||
if name != "" {
|
||||
varCache.Store(name, v)
|
||||
}
|
||||
PushOrSetFlush(Queue{
|
||||
Name: name,
|
||||
Fn: v.Flush,
|
||||
PushOrSetFlush(mockmap.Item[string, Fn]{
|
||||
Name: name,
|
||||
Value: v.Flush,
|
||||
})
|
||||
cc, ok := any(c).(clearExpired)
|
||||
if ok {
|
||||
PushOrSetClearExpired(Queue{
|
||||
Name: name,
|
||||
Fn: cc.ClearExpired,
|
||||
PushOrSetClearExpired(mockmap.Item[string, Fn]{
|
||||
Name: name,
|
||||
Value: cc.ClearExpired,
|
||||
})
|
||||
}
|
||||
return v
|
||||
|
|
44
helper/slice/mockmap/map.go
Normal file
44
helper/slice/mockmap/map.go
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user