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/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
}

View File

@ -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"),
)
}

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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

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)
}
}