Compare commits

...

7 Commits

11 changed files with 93 additions and 35 deletions

View File

@@ -31,13 +31,13 @@ type EnumDef struct {
Values []EnumDefVal Values []EnumDefVal
} }
var rexPackage = rext.W(regexp.MustCompile("^package\\s+(?P<name>[A-Za-z0-9_]+)\\s*$")) var rexPackage = rext.W(regexp.MustCompile(`^package\s+(?P<name>[A-Za-z0-9_]+)\s*$`))
var rexEnumDef = rext.W(regexp.MustCompile("^\\s*type\\s+(?P<name>[A-Za-z0-9_]+)\\s+(?P<type>[A-Za-z0-9_]+)\\s*//\\s*(@enum:type).*$")) var rexEnumDef = rext.W(regexp.MustCompile(`^\s*type\s+(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*//\s*(@enum:type).*$`))
var rexValueDef = rext.W(regexp.MustCompile("^\\s*(?P<name>[A-Za-z0-9_]+)\\s+(?P<type>[A-Za-z0-9_]+)\\s*=\\s*(?P<value>(\"[A-Za-z0-9_:]+\"|[0-9]+))\\s*(//(?P<descr>.*))?.*$")) var rexValueDef = rext.W(regexp.MustCompile(`^\s*(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*=\s*(?P<value>("[A-Za-z0-9_:]+"|[0-9]+))\s*(//(?P<descr>.*))?.*$`))
var rexChecksumConst = rext.W(regexp.MustCompile("const ChecksumGenerator = \"(?P<cs>[A-Za-z0-9_]*)\"")) var rexChecksumConst = rext.W(regexp.MustCompile(`const ChecksumGenerator = "(?P<cs>[A-Za-z0-9_]*)"`))
func GenerateEnumSpecs(sourceDir string, destFile string) error { func GenerateEnumSpecs(sourceDir string, destFile string) error {

View File

@@ -14,6 +14,9 @@ type AppContext struct {
} }
func CreateAppContext(g *gin.Context, innerCtx context.Context, cancelFn context.CancelFunc) *AppContext { func CreateAppContext(g *gin.Context, innerCtx context.Context, cancelFn context.CancelFunc) *AppContext {
for key, value := range g.Keys {
innerCtx = context.WithValue(innerCtx, key, value)
}
return &AppContext{ return &AppContext{
inner: innerCtx, inner: innerCtx,
cancelFunc: cancelFn, cancelFunc: cancelFn,
@@ -38,6 +41,10 @@ func (ac *AppContext) Value(key any) any {
return ac.inner.Value(key) return ac.inner.Value(key)
} }
func (ac *AppContext) Set(key, value any) {
ac.inner = context.WithValue(ac.inner, key, value)
}
func (ac *AppContext) Cancel() { func (ac *AppContext) Cancel() {
ac.cancelled = true ac.cancelled = true
ac.cancelFunc() ac.cancelFunc()

View File

@@ -25,7 +25,7 @@ func Wrap(w *GinWrapper, fn WHandlerFunc) gin.HandlerFunc {
Str("trace", stackTrace). Str("trace", stackTrace).
Build() Build()
wrap = Error(g, err) wrap = Error(err)
} }
if g.Writer.Written() { if g.Writer.Written() {

View File

@@ -52,7 +52,7 @@ func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
WithType(exerr.TypeBindFailURI). WithType(exerr.TypeBindFailURI).
Str("struct_type", fmt.Sprintf("%T", pctx.uri)). Str("struct_type", fmt.Sprintf("%T", pctx.uri)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} }
@@ -62,7 +62,7 @@ func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
WithType(exerr.TypeBindFailQuery). WithType(exerr.TypeBindFailQuery).
Str("struct_type", fmt.Sprintf("%T", pctx.query)). Str("struct_type", fmt.Sprintf("%T", pctx.query)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} }
@@ -73,13 +73,13 @@ func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
WithType(exerr.TypeBindFailJSON). WithType(exerr.TypeBindFailJSON).
Str("struct_type", fmt.Sprintf("%T", pctx.body)). Str("struct_type", fmt.Sprintf("%T", pctx.body)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} else { } else {
err := exerr.New(exerr.TypeBindFailJSON, "missing JSON body"). err := exerr.New(exerr.TypeBindFailJSON, "missing JSON body").
Str("struct_type", fmt.Sprintf("%T", pctx.body)). Str("struct_type", fmt.Sprintf("%T", pctx.body)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} }
@@ -90,13 +90,13 @@ func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
WithType(exerr.TypeBindFailFormData). WithType(exerr.TypeBindFailFormData).
Str("struct_type", fmt.Sprintf("%T", pctx.form)). Str("struct_type", fmt.Sprintf("%T", pctx.form)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} else { } else {
err := exerr.New(exerr.TypeBindFailFormData, "missing form body"). err := exerr.New(exerr.TypeBindFailFormData, "missing form body").
Str("struct_type", fmt.Sprintf("%T", pctx.form)). Str("struct_type", fmt.Sprintf("%T", pctx.form)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} }
@@ -106,7 +106,7 @@ func (pctx PreContext) Start() (*AppContext, *gin.Context, *HTTPResponse) {
WithType(exerr.TypeBindFailHeader). WithType(exerr.TypeBindFailHeader).
Str("struct_type", fmt.Sprintf("%T", pctx.query)). Str("struct_type", fmt.Sprintf("%T", pctx.query)).
Build() Build()
return nil, nil, langext.Ptr(Error(pctx.ginCtx, err)) return nil, nil, langext.Ptr(Error(err))
} }
} }

View File

@@ -170,12 +170,18 @@ func Redirect(sc int, newURL string) HTTPResponse {
return &redirectHTTPResponse{statusCode: sc, url: newURL} return &redirectHTTPResponse{statusCode: sc, url: newURL}
} }
func Error(g *gin.Context, e error) HTTPResponse { func Error(e error) HTTPResponse {
return &jsonAPIErrResponse{ return &jsonAPIErrResponse{
err: exerr.FromError(e), err: exerr.FromError(e),
} }
} }
func NotImplemented(g *gin.Context) HTTPResponse { func ErrWrap(e error, errorType exerr.ErrorType, msg string) HTTPResponse {
return Error(g, exerr.New(exerr.TypeNotImplemented, "").Build()) return &jsonAPIErrResponse{
err: exerr.FromError(exerr.Wrap(e, msg).WithType(errorType).Build()),
}
}
func NotImplemented() HTTPResponse {
return Error(exerr.New(exerr.TypeNotImplemented, "").Build())
} }

View File

@@ -5,6 +5,7 @@ import (
"gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/rext" "gogs.mikescher.com/BlackForestBytes/goext/rext"
"net/http" "net/http"
"path"
"reflect" "reflect"
"regexp" "regexp"
"runtime" "runtime"
@@ -20,6 +21,7 @@ var anyMethods = []string{
type GinRoutesWrapper struct { type GinRoutesWrapper struct {
wrapper *GinWrapper wrapper *GinWrapper
routes gin.IRouter routes gin.IRouter
absPath string
defaultHandler []gin.HandlerFunc defaultHandler []gin.HandlerFunc
} }
@@ -28,15 +30,26 @@ type GinRouteBuilder struct {
method string method string
relPath string relPath string
absPath string
handlers []gin.HandlerFunc handlers []gin.HandlerFunc
} }
func (w *GinWrapper) Routes() *GinRoutesWrapper { func (w *GinWrapper) Routes() *GinRoutesWrapper {
return &GinRoutesWrapper{wrapper: w, routes: w.engine} return &GinRoutesWrapper{
wrapper: w,
routes: w.engine,
absPath: "",
defaultHandler: make([]gin.HandlerFunc, 0),
}
} }
func (w *GinRoutesWrapper) Group(relativePath string) *GinRoutesWrapper { func (w *GinRoutesWrapper) Group(relativePath string) *GinRoutesWrapper {
return &GinRoutesWrapper{wrapper: w.wrapper, routes: w.routes.Group(relativePath), defaultHandler: langext.ArrCopy(w.defaultHandler)} return &GinRoutesWrapper{
wrapper: w.wrapper,
routes: w.routes.Group(relativePath),
defaultHandler: langext.ArrCopy(w.defaultHandler),
absPath: joinPaths(w.absPath, relativePath),
}
} }
func (w *GinRoutesWrapper) Use(middleware ...gin.HandlerFunc) *GinRoutesWrapper { func (w *GinRoutesWrapper) Use(middleware ...gin.HandlerFunc) *GinRoutesWrapper {
@@ -46,39 +59,49 @@ 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, method: http.MethodGet, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodGet, relativePath)
} }
func (w *GinRoutesWrapper) POST(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) POST(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodPost, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodPost, relativePath)
} }
func (w *GinRoutesWrapper) DELETE(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) DELETE(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodDelete, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodDelete, relativePath)
} }
func (w *GinRoutesWrapper) PATCH(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) PATCH(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodPatch, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodPatch, relativePath)
} }
func (w *GinRoutesWrapper) PUT(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) PUT(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodPut, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodPut, relativePath)
} }
func (w *GinRoutesWrapper) OPTIONS(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) OPTIONS(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodOptions, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodOptions, relativePath)
} }
func (w *GinRoutesWrapper) HEAD(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) HEAD(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: http.MethodHead, relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route(http.MethodHead, relativePath)
} }
func (w *GinRoutesWrapper) COUNT(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) COUNT(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: "COUNT", relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route("COUNT", relativePath)
} }
func (w *GinRoutesWrapper) Any(relativePath string) *GinRouteBuilder { func (w *GinRoutesWrapper) Any(relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{routes: w, method: "*", relPath: relativePath, handlers: langext.ArrCopy(w.defaultHandler)} return w._route("*", relativePath)
}
func (w *GinRoutesWrapper) _route(method string, relativePath string) *GinRouteBuilder {
return &GinRouteBuilder{
routes: w,
method: method,
relPath: relativePath,
absPath: joinPaths(w.absPath, relativePath),
handlers: langext.ArrCopy(w.defaultHandler),
}
} }
func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder { func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder {
@@ -106,7 +129,7 @@ func (w *GinRouteBuilder) Handle(handler WHandlerFunc) {
w.routes.wrapper.routeSpecs = append(w.routes.wrapper.routeSpecs, ginRouteSpec{ w.routes.wrapper.routeSpecs = append(w.routes.wrapper.routeSpecs, ginRouteSpec{
Method: methodName, Method: methodName,
URL: w.relPath, URL: w.absPath,
Middlewares: middlewareNames, Middlewares: middlewareNames,
Handler: handlerName, Handler: handlerName,
}) })
@@ -139,7 +162,7 @@ func nameOfFunction(f any) string {
fname = fname[:len(fname)-len("-fm")] fname = fname[:len(fname)-len("-fm")]
} }
suffix := rext.W(regexp.MustCompile("\\.func[0-9]+$")) suffix := rext.W(regexp.MustCompile(`\.func[0-9]+(?:\.[0-9]+)*$`))
if match, ok := suffix.MatchFirst(fname); ok { if match, ok := suffix.MatchFirst(fname); ok {
fname = fname[:len(fname)-match.FullMatch().Length()] fname = fname[:len(fname)-match.FullMatch().Length()]
@@ -147,3 +170,23 @@ func nameOfFunction(f any) string {
return fname return fname
} }
// joinPaths is copied verbatim from gin@v1.9.1/gin.go
func joinPaths(absolutePath, relativePath string) string {
if relativePath == "" {
return absolutePath
}
finalPath := path.Join(absolutePath, relativePath)
if lastChar(relativePath) == '/' && lastChar(finalPath) != '/' {
return finalPath + "/"
}
return finalPath
}
func lastChar(str string) uint8 {
if str == "" {
panic("The length of the string can't be 0")
}
return str[len(str)-1]
}

2
go.mod
View File

@@ -14,7 +14,7 @@ require (
) )
require ( require (
github.com/bytedance/sonic v1.10.0-rc2 // indirect github.com/bytedance/sonic v1.10.0-rc3 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect

2
go.sum
View File

@@ -2,6 +2,8 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.0-rc2 h1:oDfRZ+4m6AYCOC0GFeOCeYqvBmucy1isvouS2K0cPzo= github.com/bytedance/sonic v1.10.0-rc2 h1:oDfRZ+4m6AYCOC0GFeOCeYqvBmucy1isvouS2K0cPzo=
github.com/bytedance/sonic v1.10.0-rc2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.10.0-rc2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0=
github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.207" const GoextVersion = "0.0.214"
const GoextVersionTimestamp = "2023-07-25T10:47:00+0200" const GoextVersionTimestamp = "2023-07-27T09:58:10+0200"

View File

@@ -8,7 +8,7 @@ import (
func TestGroupByNameOrEmpty1(t *testing.T) { func TestGroupByNameOrEmpty1(t *testing.T) {
regex1 := W(regexp.MustCompile("0(?P<group1>A+)B(?P<group2>C+)0")) regex1 := W(regexp.MustCompile(`0(?P<group1>A+)B(?P<group2>C+)0`))
match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.") match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.")
@@ -26,7 +26,7 @@ func TestGroupByNameOrEmpty1(t *testing.T) {
func TestGroupByNameOrEmpty2(t *testing.T) { func TestGroupByNameOrEmpty2(t *testing.T) {
regex1 := W(regexp.MustCompile("0(?P<group1>A+)B(?P<group2>C+)(?P<group3>C+)?0")) regex1 := W(regexp.MustCompile(`0(?P<group1>A+)B(?P<group2>C+)(?P<group3>C+)?0`))
match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.") match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.")

View File

@@ -71,12 +71,12 @@ func SupportsColors() bool {
} }
} }
var term256Regex = regexp.MustCompile("(?i)-256(color)?$") var term256Regex = regexp.MustCompile(`(?i)-256(color)?$`)
if term256Regex.MatchString(termenv) { if term256Regex.MatchString(termenv) {
return true return true
} }
var termBasicRegex = regexp.MustCompile("(?i)^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux") var termBasicRegex = regexp.MustCompile(`(?i)^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux`)
if termBasicRegex.MatchString(termenv) { if termBasicRegex.MatchString(termenv) {
return true return true