This commit is contained in:
Mike Schwörer 2023-07-24 18:22:36 +02:00
parent a259bb6dbc
commit 8ae9a0f107
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
3 changed files with 113 additions and 14 deletions

View File

@ -1,8 +1,12 @@
package ginext package ginext
import ( import (
"fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/mathext"
"net/http" "net/http"
"strings"
"time" "time"
) )
@ -13,6 +17,15 @@ type GinWrapper struct {
allowCors bool allowCors bool
ginDebug bool ginDebug bool
requestTimeout time.Duration requestTimeout time.Duration
routeSpecs []ginRouteSpec
}
type ginRouteSpec struct {
Method string
URL string
Middlewares []string
Handler string
} }
func NewEngine(allowCors bool, ginDebug bool, timeout time.Duration) *GinWrapper { func NewEngine(allowCors bool, ginDebug bool, timeout time.Duration) *GinWrapper {
@ -33,18 +46,63 @@ func NewEngine(allowCors bool, ginDebug bool, timeout time.Duration) *GinWrapper
engine.Use(CorsMiddleware()) engine.Use(CorsMiddleware())
} }
// do not debug-print routes
gin.DebugPrintRouteFunc = func(_, _, _ string, _ int) {}
if ginDebug { if ginDebug {
gin.SetMode(gin.ReleaseMode)
ginlogger := gin.Logger() ginlogger := gin.Logger()
engine.Use(func(context *gin.Context) { engine.Use(func(context *gin.Context) {
if !wrapper.SuppressGinLogs { if !wrapper.SuppressGinLogs {
ginlogger(context) ginlogger(context)
} }
}) })
} else {
gin.SetMode(gin.DebugMode)
} }
return wrapper return wrapper
} }
func (w *GinWrapper) ServeHTTP(writer http.ResponseWriter, request *http.Request) { func (w *GinWrapper) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
if w.ginDebug {
w.debugPrintRoutes()
}
w.engine.ServeHTTP(writer, request) w.engine.ServeHTTP(writer, request)
} }
func (w *GinWrapper) debugPrintRoutes() {
lines := make([][4]string, 0)
pad := [4]int{0, 0, 0, 0}
for _, spec := range w.routeSpecs {
line := [4]string{
spec.Method,
spec.URL,
strings.Join(spec.Middlewares, " --> "),
spec.Method,
}
lines = append(lines, line)
pad[0] = mathext.Max(pad[0], len(line[0]))
pad[1] = mathext.Max(pad[1], len(line[1]))
pad[2] = mathext.Max(pad[2], len(line[2]))
pad[3] = mathext.Max(pad[3], len(line[3]))
}
for _, line := range lines {
fmt.Printf("Gin-Route: [%s] @ %s --> %s --> %s",
langext.StrPadRight(line[0], " ", pad[0]),
langext.StrPadRight(line[1], " ", pad[1]),
langext.StrPadRight(line[2], " ", pad[2]),
langext.StrPadRight(line[3], " ", pad[3]))
}
}

View File

@ -4,6 +4,9 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/langext"
"net/http" "net/http"
"reflect"
"runtime"
"strings"
) )
var anyMethods = []string{ var anyMethods = []string{
@ -21,7 +24,7 @@ type GinRoutesWrapper struct {
type GinRouteBuilder struct { type GinRouteBuilder struct {
routes *GinRoutesWrapper routes *GinRoutesWrapper
methods []string method string
relPath string relPath string
handlers []gin.HandlerFunc handlers []gin.HandlerFunc
} }
@ -41,39 +44,39 @@ func (w *GinRoutesWrapper) Use(middleware ...gin.HandlerFunc) *GinRoutesWrapper
} }
func (w *GinRoutesWrapper) GET(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) GET(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodGet}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodGet, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) POST(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) POST(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodPost}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodPost, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) DELETE(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) DELETE(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodDelete}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodDelete, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) PATCH(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) PATCH(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodPatch}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodPatch, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) PUT(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) PUT(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodPut}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodPut, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) OPTIONS(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) OPTIONS(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodOptions}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodOptions, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) HEAD(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) HEAD(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{http.MethodHead}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: http.MethodHead, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) COUNT(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) COUNT(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: []string{"COUNT"}, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: "COUNT", relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRoutesWrapper) Any(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) Any(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, methods: anyMethods, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return &GinRouteBuilder{routes: w, method: "*", relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)}
} }
func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder { func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder {
@ -82,12 +85,50 @@ func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder {
} }
func (w *GinRouteBuilder) Handle(handler WHandlerFunc) { func (w *GinRouteBuilder) Handle(handler WHandlerFunc) {
middlewareNames := langext.ArrMap(w.handlers, func(v gin.HandlerFunc) string { return nameOfFunction(v) })
handlerName := nameOfFunction(handler)
w.handlers = append(w.handlers, Wrap(w.routes.wrapper, handler)) w.handlers = append(w.handlers, Wrap(w.routes.wrapper, handler))
for _, m := range w.methods {
w.routes.routes.Handle(m, w.relPath, w.handlers...) methodName := w.method
if w.method == "*" {
methodName = "ANY"
for _, method := range anyMethods {
w.routes.routes.Handle(method, w.relPath, w.handlers...)
}
} else {
w.routes.routes.Handle(w.method, w.relPath, w.handlers...)
} }
w.routes.wrapper.routeSpecs = append(w.routes.wrapper.routeSpecs, ginRouteSpec{
Method: methodName,
URL: w.relPath,
Middlewares: middlewareNames,
Handler: handlerName,
})
} }
func (w *GinWrapper) NoRoute(handler WHandlerFunc) { func (w *GinWrapper) NoRoute(handler WHandlerFunc) {
w.engine.NoRoute(Wrap(w, handler)) w.engine.NoRoute(Wrap(w, handler))
w.routeSpecs = append(w.routeSpecs, ginRouteSpec{
Method: "ANY",
URL: "[NO_ROUTE]",
Middlewares: nil,
Handler: nameOfFunction(handler),
})
}
func nameOfFunction(f any) string {
n := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
split := strings.Split(n, "/")
if len(split) == 0 {
return ""
}
return split[len(split)-1]
} }

View File

@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.200" const GoextVersion = "0.0.201"
const GoextVersionTimestamp = "2023-07-24T17:42:18+0200" const GoextVersionTimestamp = "2023-07-24T18:22:36+0200"