Fetch the repository succeeded.
package mweb
import (
"context"
"fmt"
"gitee.com/dennis-mxx/mxx-core-v2/menv"
"gitee.com/dennis-mxx/mxx-core-v2/mexception"
"gitee.com/dennis-mxx/mxx-core-v2/mlogger"
"gitee.com/dennis-mxx/mxx-core-v2/mmodel"
"gitee.com/dennis-mxx/mxx-core-v2/mutil"
"github.com/gin-gonic/gin"
"net/http"
"os"
"os/signal"
"path"
"strconv"
"strings"
"syscall"
"time"
)
var Engine *GinEngine
type XXHandlerFunc func(stx SessionCtx, ctx *gin.Context) (result any, err error)
type SessionCtxFunc func(ctx *gin.Context) SessionCtx
type ErrorHandler func(err error, stx SessionCtx, ctx *gin.Context)
type ResultFunc func(stx SessionCtx, ctx *gin.Context, result any, err error)
type LoaderHandler interface {
Loader(engine *GinEngine)
}
type GinEngine struct {
*gin.Engine
BasePath string
SessionId string
Port int64
Stx SessionCtxFunc
ResFunc ResultFunc
ErrHandler ErrorHandler
}
func InitWeb(ginOption *menv.Gin) {
if ginOption.Mode != "" {
gin.SetMode(ginOption.Mode)
}
InitSession()
web := gin.New()
Engine = &GinEngine{Engine: web}
Engine.SessionId = ginOption.SessionId
if strings.HasSuffix(ginOption.BasePath, "/") {
Engine.BasePath = ginOption.BasePath[0 : len(ginOption.BasePath)-1]
} else {
Engine.BasePath = ginOption.BasePath
}
Engine.Port = ginOption.Port
Engine.Stx = func(ctx *gin.Context) SessionCtx {
return &SessionCtxDefault{
sessionId: Engine.SessionId,
ctx: ctx,
}
}
Engine.ResFunc = func(stx SessionCtx, ctx *gin.Context, result any, err error) {
if err != nil {
ctx.AbortWithStatusJSON(200, mmodel.Failure(-1, "exception", (err.(error)).Error()))
} else if result != nil {
ctx.AbortWithStatusJSON(200, result)
}
}
Engine.ErrHandler = func(err error, stx SessionCtx, ctx *gin.Context) {
mlogger.Out.Error("interface exception [", ctx.Request.RequestURI, "] ", err)
ctx.AbortWithStatusJSON(200, mmodel.Failure(-1, "exception", err.Error()))
}
ip, _ := mutil.LocalIP()
mlogger.Out.Info(fmt.Sprintf("Initialize [Gin Port : %v , Session: %v , Url : http://%s:%v%s ]", ginOption.Port, ginOption.Session, ip, ginOption.Port, ginOption.BasePath))
}
func (domain *GinEngine) WithMiddleware(listens ...gin.RecoveryFunc) *GinEngine {
if menv.Environment.Value == "pro" {
domain.Use(gin.LoggerWithWriter(mlogger.GetWriter()))
} else {
domain.Use(gin.Logger())
}
domain.Use(gin.CustomRecovery(func(ctx *gin.Context, err any) {
if vr, ok := err.(mexception.Exception); ok {
ctx.AbortWithStatusJSON(200, mmodel.Failure(vr.Code, "exception", vr.Error()))
} else {
ctx.AbortWithStatusJSON(200, mmodel.Failure(-1, "exception", (err.(error)).Error()))
}
for _, listen := range listens {
listen(ctx, err)
}
}))
return domain
}
func (domain *GinEngine) WithLogger() *GinEngine {
if menv.Environment.Value == "pro" {
domain.Use(gin.LoggerWithWriter(mlogger.GetWriter()))
} else {
domain.Use(gin.Logger())
}
return domain
}
func (domain *GinEngine) XXHandler(httpMethod, relativePath string, handler XXHandlerFunc) {
domain.Handle(httpMethod, domain.getPath(relativePath), domain.GetXXHandler(handler))
}
func (domain *GinEngine) XXDel(relativePath string, handler XXHandlerFunc) {
domain.Handle("DELETE", domain.getPath(relativePath), domain.GetXXHandler(handler))
}
func (domain *GinEngine) XXGet(relativePath string, handler XXHandlerFunc) {
domain.Handle("GET", domain.getPath(relativePath), domain.GetXXHandler(handler))
}
func (domain *GinEngine) XXLoader(loaders ...LoaderHandler) {
for _, loader := range loaders {
loader.Loader(domain)
}
}
func (domain *GinEngine) XXPost(relativePath string, handler XXHandlerFunc) {
domain.Handle("POST", domain.getPath(relativePath), domain.GetXXHandler(handler))
}
func (domain *GinEngine) XXPut(relativePath string, handler XXHandlerFunc) {
domain.Handle("PUT", domain.getPath(relativePath), domain.GetXXHandler(handler))
}
func (domain *GinEngine) GetXXHandler(handler XXHandlerFunc) gin.HandlerFunc {
return func(ctx *gin.Context) {
session := domain.Stx(ctx)
defer func() {
if err := recover(); err != nil {
domain.ErrHandler(err.(error), session, ctx)
}
}()
result, err := handler(session, ctx)
domain.ResFunc(session, ctx, result, err)
}
}
func (domain *GinEngine) XXRun() {
builder := strings.Builder{}
builder.WriteString(":")
builder.WriteString(strconv.FormatInt(domain.Port, 10))
srv := &http.Server{
Addr: builder.String(),
Handler: domain.Engine,
}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
mlogger.Out.Info("listen:%s\n", err)
}
}()
// wait for interrupt signal to gracefully shutdown the server with
// a timeout of 10 seconds.
quit := make(chan os.Signal, 1)
// kill (no param) default send syscall.SIGTERM
// kill -2 is syscall.SIGINT
// kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
mlogger.Out.Info("Shutdown Server ...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
mlogger.Out.Fatal("Server Shutdown:", err)
}
mlogger.Out.Info("Server exiting")
}
func (domain *GinEngine) With404JSON() *GinEngine {
domain.Use(func(ctx *gin.Context) {
if ctx.Writer.Status() == 404 {
ctx.JSON(404, mmodel.Failure(404, "404", "PATH NOT FOUND"))
}
ctx.Next()
})
return domain
}
func (domain *GinEngine) WithCors(allowHeaders ...string) *GinEngine {
allowString := strings.Join(allowHeaders, ", ")
domain.Use(func(ctx *gin.Context) {
ctx.Header("Access-Control-Allow-Origin", ctx.GetHeader("Origin")) // 注意这一行,不能配置为通配符“*”号
ctx.Header("Access-Control-Allow-Credentials", "true") // 注意这一行,必须设定为 true
ctx.Header("Access-Control-Allow-Headers", allowString) // 我们自定义的header字段都需要在这里声明
ctx.Header("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,PUT")
ctx.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type,cache-control")
if ctx.Request.Method == "OPTIONS" {
ctx.AbortWithStatus(http.StatusNoContent)
return
}
ctx.Next()
})
return domain
}
func (domain *GinEngine) getPath(relativePath string) string {
return path.Join(domain.BasePath, relativePath)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。