mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
DBUG API: mark overlapped routes, hide the builtin functionality (read description)
also reference the correct file:line on <autogenerated> (by searching for the file,line of method inside the embedded fields themselves, as go automatically generates the methods foreach struct for their embedded fields) fix UseGlobal may override the overlap feature
This commit is contained in:
parent
0b31b50404
commit
6f9a453160
|
@ -178,9 +178,8 @@ func overlapRoute(r *Route, next *Route) {
|
||||||
ctx.Do(nextHandlers)
|
ctx.Do(nextHandlers)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(@kataras): Any UseGlobal call will prepend to this, if they are
|
r.builtinBeginHandlers = append(context.Handlers{decisionHandler}, r.builtinBeginHandlers...)
|
||||||
// in the same Party then it's expected, otherwise not.
|
r.overlappedLink = next
|
||||||
r.beginHandlers = append(context.Handlers{decisionHandler}, r.beginHandlers...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// APIBuilder the visible API for constructing the router
|
// APIBuilder the visible API for constructing the router
|
||||||
|
@ -411,7 +410,7 @@ func (api *APIBuilder) handle(errorCode int, method string, relativePath string,
|
||||||
var err error
|
var err error
|
||||||
for _, route = range routes {
|
for _, route = range routes {
|
||||||
if route == nil {
|
if route == nil {
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// global
|
// global
|
||||||
|
|
|
@ -311,10 +311,9 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
||||||
return errgroup.Check(rp)
|
return errgroup.Check(rp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindMultiParamTypesHandler(r *Route) {
|
func bindMultiParamTypesHandler(r *Route) { // like overlap feature but specifically for path parameters.
|
||||||
r.BuildHandlers()
|
r.BuildHandlers()
|
||||||
|
|
||||||
// println("here for top: " + top.Name + " and current route: " + r.Name)
|
|
||||||
h := r.Handlers[1:] // remove the macro evaluator handler as we manually check below.
|
h := r.Handlers[1:] // remove the macro evaluator handler as we manually check below.
|
||||||
f := macroHandler.MakeFilter(r.tmpl)
|
f := macroHandler.MakeFilter(r.tmpl)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
|
@ -347,7 +346,7 @@ func bindMultiParamTypesHandler(r *Route) {
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
r.topLink.beginHandlers = append(context.Handlers{decisionHandler}, r.topLink.beginHandlers...)
|
r.topLink.builtinBeginHandlers = append(context.Handlers{decisionHandler}, r.topLink.builtinBeginHandlers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func canHandleSubdomain(ctx *context.Context, subdomain string) bool {
|
func canHandleSubdomain(ctx *context.Context, subdomain string) bool {
|
||||||
|
|
|
@ -29,7 +29,14 @@ type Route struct {
|
||||||
tmpl macro.Template // Tmpl().Src: "/api/user/{id:uint64}"
|
tmpl macro.Template // Tmpl().Src: "/api/user/{id:uint64}"
|
||||||
// temp storage, they're appended to the Handlers on build.
|
// temp storage, they're appended to the Handlers on build.
|
||||||
// Execution happens before Handlers, can be empty.
|
// Execution happens before Handlers, can be empty.
|
||||||
|
// They run right after any builtinBeginHandlers.
|
||||||
beginHandlers context.Handlers
|
beginHandlers context.Handlers
|
||||||
|
// temp storage, these are always registered first as Handlers on Build.
|
||||||
|
// There are the handlers may be added by the framework and
|
||||||
|
// can NOT be modified by the end-developer (i.e overlapRoute & bindMultiParamTypesHandler),
|
||||||
|
// even if a function like UseGlobal is used.
|
||||||
|
builtinBeginHandlers context.Handlers
|
||||||
|
|
||||||
// Handlers are the main route's handlers, executed by order.
|
// Handlers are the main route's handlers, executed by order.
|
||||||
// Cannot be empty.
|
// Cannot be empty.
|
||||||
Handlers context.Handlers `json:"-"`
|
Handlers context.Handlers `json:"-"`
|
||||||
|
@ -52,7 +59,13 @@ type Route struct {
|
||||||
RegisterFileName string `json:"registerFileName"`
|
RegisterFileName string `json:"registerFileName"`
|
||||||
RegisterLineNumber int `json:"registerLineNumber"`
|
RegisterLineNumber int `json:"registerLineNumber"`
|
||||||
|
|
||||||
|
// see APIBuilder.handle, routerHandler.bindMultiParamTypesHandler and routerHandler.Build,
|
||||||
|
// it's the parent route of the last registered of the same path parameter. Specifically for path parameters.
|
||||||
topLink *Route
|
topLink *Route
|
||||||
|
// overlappedLink specifically for overlapRoute feature.
|
||||||
|
// keeps the second route of the same path pattern registered.
|
||||||
|
// It's used ONLY for logging.
|
||||||
|
overlappedLink *Route
|
||||||
|
|
||||||
// Sitemap properties: https://www.sitemaps.org/protocol.html
|
// Sitemap properties: https://www.sitemaps.org/protocol.html
|
||||||
LastMod time.Time `json:"lastMod,omitempty"`
|
LastMod time.Time `json:"lastMod,omitempty"`
|
||||||
|
@ -189,15 +202,15 @@ func (r *Route) BuildHandlers() {
|
||||||
r.OnBuild(r)
|
r.OnBuild(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.beginHandlers) > 0 {
|
// prepend begin handlers.
|
||||||
r.Handlers = append(r.beginHandlers, r.Handlers...)
|
r.Handlers = append(r.builtinBeginHandlers, append(r.beginHandlers, r.Handlers...)...)
|
||||||
r.beginHandlers = r.beginHandlers[0:0]
|
// append done handlers.
|
||||||
}
|
r.Handlers = append(r.Handlers, r.doneHandlers...)
|
||||||
|
// reset the temp storage, so a second call of
|
||||||
if len(r.doneHandlers) > 0 {
|
// BuildHandlers will not re-add them (i.e RefreshRouter).
|
||||||
r.Handlers = append(r.Handlers, r.doneHandlers...)
|
r.builtinBeginHandlers = r.builtinBeginHandlers[0:0]
|
||||||
r.doneHandlers = r.doneHandlers[0:0]
|
r.beginHandlers = r.beginHandlers[0:0]
|
||||||
} // note: no mutex needed, this should be called in-sync when server is not running of course.
|
r.doneHandlers = r.doneHandlers[0:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the form of METHOD, SUBDOMAIN, TMPL PATH.
|
// String returns the form of METHOD, SUBDOMAIN, TMPL PATH.
|
||||||
|
@ -494,6 +507,13 @@ func (r *Route) Trace(w io.Writer, stoppedIndex int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintln(w)
|
fmt.Fprintln(w)
|
||||||
|
|
||||||
|
if r.overlappedLink != nil {
|
||||||
|
bckpDesc := r.overlappedLink.Description
|
||||||
|
r.overlappedLink.Description += " (overlapped)"
|
||||||
|
r.overlappedLink.Trace(w, -1)
|
||||||
|
r.overlappedLink.Description = bckpDesc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type routeReadOnlyWrapper struct {
|
type routeReadOnlyWrapper struct {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kataras/iris/v12"
|
|
||||||
"github.com/kataras/iris/v12/context"
|
"github.com/kataras/iris/v12/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ func (b *basicAuthMiddleware) findAuth(headerValue string) (*encodedUser, bool)
|
||||||
|
|
||||||
func (b *basicAuthMiddleware) askForCredentials(ctx *context.Context) {
|
func (b *basicAuthMiddleware) askForCredentials(ctx *context.Context) {
|
||||||
ctx.Header("WWW-Authenticate", b.realmHeaderValue)
|
ctx.Header("WWW-Authenticate", b.realmHeaderValue)
|
||||||
ctx.StatusCode(iris.StatusUnauthorized)
|
ctx.StatusCode(401)
|
||||||
if b.askHandlerEnabled {
|
if b.askHandlerEnabled {
|
||||||
b.config.OnAsk(ctx)
|
b.config.OnAsk(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,13 +415,19 @@ func (c *ControllerActivator) handleMany(method, path, funcName string, override
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ControllerActivator) saveRoutes(funcName string, routes []*router.Route, override bool) {
|
func (c *ControllerActivator) saveRoutes(funcName string, routes []*router.Route, override bool) {
|
||||||
|
m, ok := c.Type.MethodByName(funcName)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceFileName, sourceLineNumber := getSourceFileLine(c.Type, m)
|
||||||
|
|
||||||
relName := c.RelName()
|
relName := c.RelName()
|
||||||
for _, r := range routes {
|
for _, r := range routes {
|
||||||
r.Description = relName
|
r.Description = relName
|
||||||
r.MainHandlerName = fmt.Sprintf("%s.%s", relName, funcName)
|
r.MainHandlerName = fmt.Sprintf("%s.%s", relName, funcName)
|
||||||
if m, ok := c.Type.MethodByName(funcName); ok {
|
|
||||||
r.SourceFileName, r.SourceLineNumber = context.HandlerFileLineRel(m.Func)
|
r.SourceFileName, r.SourceLineNumber = sourceFileName, sourceLineNumber
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add this as a reserved method name in order to
|
// add this as a reserved method name in order to
|
||||||
|
|
|
@ -2,6 +2,8 @@ package mvc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/v12/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
|
||||||
|
@ -20,3 +22,37 @@ func indirectType(typ reflect.Type) reflect.Type {
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSourceFileLine(ctrlType reflect.Type, m reflect.Method) (string, int) { // used for debug logs.
|
||||||
|
sourceFileName, sourceLineNumber := context.HandlerFileLineRel(m.Func)
|
||||||
|
if sourceFileName == "<autogenerated>" {
|
||||||
|
elem := indirectType(ctrlType)
|
||||||
|
|
||||||
|
for i, n := 0, elem.NumField(); i < n; i++ {
|
||||||
|
if f := elem.Field(i); f.Anonymous {
|
||||||
|
typ := indirectType(f.Type)
|
||||||
|
if typ.Kind() != reflect.Struct {
|
||||||
|
continue // field is not a struct.
|
||||||
|
}
|
||||||
|
|
||||||
|
// why we do that?
|
||||||
|
// because if the element is not Ptr
|
||||||
|
// then it's probably used as:
|
||||||
|
// type ctrl {
|
||||||
|
// BaseCtrl
|
||||||
|
// }
|
||||||
|
// but BaseCtrl has not the method, *BaseCtrl does:
|
||||||
|
// (c *BaseCtrl) HandleHTTPError(...)
|
||||||
|
// so we are creating a new temporarly value ptr of that type
|
||||||
|
// and searching inside it for the method instead.
|
||||||
|
typ = reflect.New(typ).Type()
|
||||||
|
|
||||||
|
if embeddedMethod, ok := typ.MethodByName(m.Name); ok {
|
||||||
|
sourceFileName, sourceLineNumber = context.HandlerFileLineRel(embeddedMethod.Func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourceFileName, sourceLineNumber
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user