Fix Services & Update the middleware && others

This commit is contained in:
XOF
2025-11-24 04:48:07 +08:00
parent 3a95a07e8a
commit f2706d6fc8
37 changed files with 4458 additions and 1166 deletions

View File

@@ -1,63 +1,96 @@
// Filename: internal/pongo/renderer.go
package pongo
import (
"fmt"
"net/http"
"sync"
"github.com/flosch/pongo2/v6"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/render"
"github.com/sirupsen/logrus"
)
type Renderer struct {
Context pongo2.Context
tplSet *pongo2.TemplateSet
mu sync.RWMutex
globalContext pongo2.Context
tplSet *pongo2.TemplateSet
logger *logrus.Logger
}
func New(directory string, isDebug bool) *Renderer {
func New(directory string, isDebug bool, logger *logrus.Logger) *Renderer {
loader := pongo2.MustNewLocalFileSystemLoader(directory)
tplSet := pongo2.NewSet("gin-pongo-templates", loader)
tplSet.Debug = isDebug
return &Renderer{Context: make(pongo2.Context), tplSet: tplSet}
return &Renderer{
globalContext: make(pongo2.Context),
tplSet: tplSet,
logger: logger,
}
}
// Instance returns a new render.HTML instance for a single request.
func (p *Renderer) Instance(name string, data interface{}) render.Render {
var glob pongo2.Context
if p.Context != nil {
glob = p.Context
}
// SetGlobalContext 线程安全地设置全局上下文
func (p *Renderer) SetGlobalContext(key string, value interface{}) {
p.mu.Lock()
defer p.mu.Unlock()
p.globalContext[key] = value
}
// Warmup 预加载模板
func (p *Renderer) Warmup(templateNames ...string) error {
for _, name := range templateNames {
if _, err := p.tplSet.FromCache(name); err != nil {
return fmt.Errorf("failed to warmup template '%s': %w", name, err)
}
}
p.logger.WithField("count", len(templateNames)).Info("Templates warmed up")
return nil
}
func (p *Renderer) Instance(name string, data interface{}) render.Render {
// 安全读取全局上下文
p.mu.RLock()
glob := make(pongo2.Context, len(p.globalContext))
for k, v := range p.globalContext {
glob[k] = v
}
p.mu.RUnlock()
// 解析请求数据
var context pongo2.Context
if data != nil {
if ginContext, ok := data.(gin.H); ok {
context = pongo2.Context(ginContext)
} else if pongoContext, ok := data.(pongo2.Context); ok {
context = pongoContext
} else if m, ok := data.(map[string]interface{}); ok {
context = m
} else {
switch v := data.(type) {
case gin.H:
context = pongo2.Context(v)
case pongo2.Context:
context = v
case map[string]interface{}:
context = v
default:
context = make(pongo2.Context)
}
} else {
context = make(pongo2.Context)
}
// 合并上下文(请求数据优先)
for k, v := range glob {
if _, ok := context[k]; !ok {
if _, exists := context[k]; !exists {
context[k] = v
}
}
// 加载模板
tpl, err := p.tplSet.FromCache(name)
if err != nil {
panic(fmt.Sprintf("Failed to load template '%s': %v", name, err))
p.logger.WithError(err).WithField("template", name).Error("Failed to load template")
return &ErrorHTML{
StatusCode: http.StatusInternalServerError,
Error: fmt.Errorf("template load error: %s", name),
}
}
return &HTML{
p: p,
Template: tpl,
Name: name,
Data: context,
@@ -65,7 +98,6 @@ func (p *Renderer) Instance(name string, data interface{}) render.Render {
}
type HTML struct {
p *Renderer
Template *pongo2.Template
Name string
Data pongo2.Context
@@ -82,15 +114,31 @@ func (h *HTML) Render(w http.ResponseWriter) error {
}
func (h *HTML) WriteContentType(w http.ResponseWriter) {
header := w.Header()
if val := header["Content-Type"]; len(val) == 0 {
header["Content-Type"] = []string{"text/html; charset=utf-8"}
if w.Header().Get("Content-Type") == "" {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
}
}
// ErrorHTML 错误渲染器
type ErrorHTML struct {
StatusCode int
Error error
}
func (e *ErrorHTML) Render(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(e.StatusCode)
_, err := w.Write([]byte(e.Error.Error()))
return err
}
func (e *ErrorHTML) WriteContentType(w http.ResponseWriter) {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
}
// C 获取或创建 pongo2 上下文
func C(ctx *gin.Context) pongo2.Context {
p, exists := ctx.Get("pongo2")
if exists {
if p, exists := ctx.Get("pongo2"); exists {
if pCtx, ok := p.(pongo2.Context); ok {
return pCtx
}