mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 07:20:35 +01:00
more route info improvements
Former-commit-id: ccbe95de0badb1bf448fcc443cecda60772716dc
This commit is contained in:
parent
128cd255cb
commit
2a4043a3c2
|
@ -35,6 +35,8 @@ func configureAPI(api *iris.APIContainer) {
|
|||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Logger().SetLevel("debug")
|
||||
|
||||
app.ConfigureContainer(configureAPI)
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ var cacheHandler = cache.Handler(10 * time.Second)
|
|||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Logger().SetLevel("debug")
|
||||
|
||||
mvc.Configure(app, configure)
|
||||
|
||||
// http://localhost:8080
|
||||
|
|
|
@ -103,7 +103,7 @@ func main() {
|
|||
usersRoutes.Delete("/{id:uint64}", func(ctx iris.Context) {
|
||||
id, _ := ctx.Params().GetUint64("id")
|
||||
ctx.Writef("delete user by id: %d", id)
|
||||
}).SetDescription("deletes a user")
|
||||
}).Describe("deletes a user")
|
||||
|
||||
// Subdomains, depends on the host, you have to edit the hosts or nginx/caddy's configuration if you use them.
|
||||
//
|
||||
|
|
4
cache/client/handler.go
vendored
4
cache/client/handler.go
vendored
|
@ -9,6 +9,10 @@ import (
|
|||
"github.com/kataras/iris/v12/context"
|
||||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/cache/client.(*Handler).ServeHTTP-fm", "iris.cache")
|
||||
}
|
||||
|
||||
// Handler the local cache service handler contains
|
||||
// the original response, the memory cache entry and
|
||||
// the validator for each of the incoming requests and post responses
|
||||
|
|
|
@ -19,7 +19,7 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
handlerNames = make(map[*regexp.Regexp]string)
|
||||
handlerNames = make(map[*nameExpr]string)
|
||||
handlerNamesMu sync.RWMutex
|
||||
)
|
||||
|
||||
|
@ -39,10 +39,35 @@ func SetHandlerName(original string, replacement string) {
|
|||
}
|
||||
|
||||
handlerNamesMu.Lock()
|
||||
handlerNames[regexp.MustCompile(original)] = replacement
|
||||
// If regexp syntax is wrong
|
||||
// then its `MatchString` will compare through literal. Fixes an issue
|
||||
// when a handler name is declared as it's and cause regex parsing expression error,
|
||||
// e.g. `iris/cache/client.(*Handler).ServeHTTP-fm`
|
||||
regex, _ := regexp.Compile(original)
|
||||
handlerNames[&nameExpr{
|
||||
literal: original,
|
||||
regex: regex,
|
||||
}] = replacement
|
||||
handlerNamesMu.Unlock()
|
||||
}
|
||||
|
||||
type nameExpr struct {
|
||||
regex *regexp.Regexp
|
||||
literal string
|
||||
}
|
||||
|
||||
func (expr *nameExpr) MatchString(s string) bool {
|
||||
if expr.literal == s { // if matches as string, as it's.
|
||||
return true
|
||||
}
|
||||
|
||||
if expr.regex != nil {
|
||||
return expr.regex.MatchString(s)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// A Handler responds to an HTTP request.
|
||||
// It writes reply headers and data to the Context.ResponseWriter() and then return.
|
||||
// Returning signals that the request is finished;
|
||||
|
@ -79,20 +104,16 @@ func HandlerName(h interface{}) string {
|
|||
pc := valueOf(h).Pointer()
|
||||
name := runtime.FuncForPC(pc).Name()
|
||||
handlerNamesMu.RLock()
|
||||
for regex, newName := range handlerNames {
|
||||
if regex.String() == name { // if matches as string, as it's.
|
||||
name = newName
|
||||
break
|
||||
}
|
||||
|
||||
if regex.MatchString(name) {
|
||||
for expr, newName := range handlerNames {
|
||||
if expr.MatchString(name) {
|
||||
name = newName
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
handlerNamesMu.RUnlock()
|
||||
|
||||
return name
|
||||
return trimHandlerName(name)
|
||||
}
|
||||
|
||||
// HandlerFileLine returns the handler's file and line information.
|
||||
|
@ -118,21 +139,98 @@ func HandlerFileLineRel(h interface{}) (file string, line int) {
|
|||
|
||||
// MainHandlerName tries to find the main handler that end-developer
|
||||
// registered on the provided chain of handlers and returns its function name.
|
||||
func MainHandlerName(handlers Handlers) (name string, index int) {
|
||||
for i := 0; i < len(handlers); i++ {
|
||||
name = HandlerName(handlers[i])
|
||||
index = i
|
||||
if !strings.HasPrefix(name, "github.com/kataras/iris/v12") ||
|
||||
strings.HasPrefix(name, "github.com/kataras/iris/v12/core/router.StripPrefix") ||
|
||||
strings.HasPrefix(name, "github.com/kataras/iris/v12/core/router.FileServer") {
|
||||
break
|
||||
func MainHandlerName(handlers ...interface{}) (name string, index int) {
|
||||
if len(handlers) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if hs, ok := handlers[0].(Handlers); ok {
|
||||
tmp := make([]interface{}, 0, len(hs))
|
||||
for _, h := range hs {
|
||||
tmp = append(tmp, h)
|
||||
}
|
||||
|
||||
return MainHandlerName(tmp...)
|
||||
}
|
||||
|
||||
for i := 0; i < len(handlers); i++ {
|
||||
name = HandlerName(handlers[i])
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
index = i
|
||||
if !ingoreMainHandlerName(name) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func trimHandlerName(name string) string {
|
||||
// trim the path for Iris' internal middlewares, e.g.
|
||||
// irs/mvc.GRPC.Apply.func1
|
||||
if internalName := PackageName; strings.HasPrefix(name, internalName) {
|
||||
name = strings.Replace(name, internalName, "iris", 1)
|
||||
}
|
||||
|
||||
if internalName := "github.com/iris-contrib/middleware"; strings.HasPrefix(name, internalName) {
|
||||
name = strings.Replace(name, internalName, "iris-contrib", 1)
|
||||
}
|
||||
|
||||
name = strings.TrimSuffix(name, ".func1")
|
||||
return name
|
||||
}
|
||||
|
||||
var ignoreHandlerNames = [...]string{
|
||||
"iris/macro/handler.MakeHandler",
|
||||
"iris/hero.makeHandler.func2",
|
||||
"iris/core/router.ExecutionOptions.buildHandler",
|
||||
"iris/core/router.(*APIBuilder).Favicon",
|
||||
"iris/core/router.StripPrefix",
|
||||
}
|
||||
|
||||
// IgnoreHandlerName compares a static slice of Iris builtin
|
||||
// internal methods that should be ignored from trace.
|
||||
// Some internal methods are kept out of this list for actual debugging.
|
||||
func IgnoreHandlerName(name string) bool {
|
||||
for _, ignore := range ignoreHandlerNames {
|
||||
if name == ignore {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
var ignoreMainHandlerNames = [...]string{
|
||||
"iris.cache",
|
||||
"iris.basicauth",
|
||||
"iris.hCaptcha",
|
||||
"iris.reCAPTCHA",
|
||||
"iris.profiling",
|
||||
"iris.recover",
|
||||
}
|
||||
|
||||
// ingoreMainHandlerName reports whether a main handler of "name" should
|
||||
// be ignored and continue to match the next.
|
||||
// The ignored main handler names are literals and respects the `ignoreNameHandlers` too.
|
||||
func ingoreMainHandlerName(name string) bool {
|
||||
if IgnoreHandlerName(name) {
|
||||
// If ignored at all, it can't be the main.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, ignore := range ignoreMainHandlerNames {
|
||||
if name == ignore {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Filter is just a type of func(Handler) bool which reports whether an action must be performed
|
||||
// based on the incoming request.
|
||||
//
|
||||
|
|
|
@ -399,7 +399,7 @@ func (api *APIBuilder) HandleDir(requestPath, directory string, opts ...DirOptio
|
|||
for _, route := range routes {
|
||||
if route.Method == http.MethodHead {
|
||||
} else {
|
||||
route.SetDescription(description)
|
||||
route.Describe(description)
|
||||
route.SetSourceLine(fileName, lineNumber)
|
||||
}
|
||||
|
||||
|
@ -453,6 +453,7 @@ func (api *APIBuilder) CreateRoutes(methods []string, relativePath string, handl
|
|||
// before join the middleware + handlers + done handlers and apply the execution rules.
|
||||
|
||||
mainHandlerName, mainHandlerIndex := context.MainHandlerName(mainHandlers)
|
||||
|
||||
mainHandlerFileName, mainHandlerFileNumber := context.HandlerFileLineRel(handlers[mainHandlerIndex])
|
||||
|
||||
// re-calculate mainHandlerIndex in favor of the middlewares.
|
||||
|
@ -939,7 +940,7 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
|
|||
reqPath = requestPath[0]
|
||||
}
|
||||
|
||||
return api.registerResourceRoute(reqPath, h).SetDescription(description)
|
||||
return api.registerResourceRoute(reqPath, h).Describe(description)
|
||||
}
|
||||
|
||||
// OnErrorCode registers an error http status code
|
||||
|
|
|
@ -117,7 +117,15 @@ func (api *APIContainer) Done(handlersFn ...interface{}) {
|
|||
// See `OnError`, `RegisterDependency`, `Use`, `Done`, `Get`, `Post`, `Put`, `Patch` and `Delete` too.
|
||||
func (api *APIContainer) Handle(method, relativePath string, handlersFn ...interface{}) *Route {
|
||||
handlers := api.convertHandlerFuncs(relativePath, handlersFn...)
|
||||
return api.Self.Handle(method, relativePath, handlers...)
|
||||
route := api.Self.Handle(method, relativePath, handlers...)
|
||||
|
||||
// Fix main handler name and source modified by execution rules wrapper.
|
||||
route.MainHandlerName, route.MainHandlerIndex = context.MainHandlerName(handlersFn...)
|
||||
if len(handlersFn) > route.MainHandlerIndex {
|
||||
route.SourceFileName, route.SourceLineNumber = context.HandlerFileLineRel(handlersFn[route.MainHandlerIndex])
|
||||
}
|
||||
|
||||
return route
|
||||
}
|
||||
|
||||
// Get registers a route for the Get HTTP Method.
|
||||
|
|
|
@ -145,11 +145,11 @@ func (r *Route) SetStatusOffline() bool {
|
|||
return r.ChangeMethod(MethodNone)
|
||||
}
|
||||
|
||||
// SetDescription sets the route's description
|
||||
// Describe sets the route's description
|
||||
// that will be logged alongside with the route information
|
||||
// in DEBUG log level.
|
||||
// Returns the `Route` itself.
|
||||
func (r *Route) SetDescription(description string) *Route {
|
||||
func (r *Route) Describe(description string) *Route {
|
||||
r.Description = description
|
||||
return r
|
||||
}
|
||||
|
@ -341,38 +341,10 @@ func (r *Route) ResolvePath(args ...string) string {
|
|||
return formattedPath
|
||||
}
|
||||
|
||||
var ignoreHandlersTraces = [...]string{
|
||||
"iris/macro/handler.MakeHandler",
|
||||
"iris/hero.makeHandler.func2",
|
||||
"iris/core/router.(*APIBuilder).Favicon",
|
||||
"iris/core/router.StripPrefix",
|
||||
}
|
||||
|
||||
func ignoreHandlerTrace(name string) bool {
|
||||
for _, ignore := range ignoreHandlersTraces {
|
||||
if name == ignore {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func traceHandlerFile(method, name, line string, number int) string {
|
||||
file := fmt.Sprintf("(%s:%d)", line, number)
|
||||
|
||||
// trim the path for Iris' internal middlewares, e.g.
|
||||
// irs/mvc.GRPC.Apply.func1
|
||||
if internalName := context.PackageName; strings.HasPrefix(name, internalName) {
|
||||
name = strings.Replace(name, internalName, "iris", 1)
|
||||
}
|
||||
if internalName := "github.com/iris-contrib/middleware"; strings.HasPrefix(name, internalName) {
|
||||
name = strings.Replace(name, internalName, "iris-contrib", 1)
|
||||
}
|
||||
|
||||
name = strings.TrimSuffix(name, ".func1")
|
||||
|
||||
if ignoreHandlerTrace(name) {
|
||||
if context.IgnoreHandlerName(name) {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -457,7 +429,7 @@ func (r *Route) Trace(w io.Writer) {
|
|||
line int
|
||||
)
|
||||
|
||||
if i == r.MainHandlerIndex {
|
||||
if i == r.MainHandlerIndex && r.MainHandlerName != "" {
|
||||
// Main handler info can be programmatically
|
||||
// changed to be more specific, respect these changes.
|
||||
name = r.MainHandlerName
|
||||
|
@ -466,7 +438,6 @@ func (r *Route) Trace(w io.Writer) {
|
|||
} else {
|
||||
name = context.HandlerName(h)
|
||||
file, line = context.HandlerFileLineRel(h)
|
||||
|
||||
// If a middleware, e.g (macro) which changes the main handler index,
|
||||
// skip it.
|
||||
if file == r.SourceFileName && line == r.SourceLineNumber {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/basicauth.*", "Basic Authentication")
|
||||
context.SetHandlerName("iris/middleware/basicauth.*", "iris.basicauth")
|
||||
}
|
||||
|
||||
type (
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/hcaptcha.*", "hCaptcha")
|
||||
context.SetHandlerName("iris/middleware/hcaptcha.*", "iris.hCaptcha")
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/logger.*", "Request Logger")
|
||||
context.SetHandlerName("iris/middleware/logger.*", "iris.logger")
|
||||
}
|
||||
|
||||
type requestLoggerMiddleware struct {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/pprof.*", "Profiling")
|
||||
context.SetHandlerName("iris/middleware/pprof.*", "iris.profiling")
|
||||
}
|
||||
|
||||
// New returns a new pprof (profile, cmdline, symbol, goroutine, heap, threadcreate, debug/block) Middleware.
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/recaptcha.*", "reCAPTCHA")
|
||||
context.SetHandlerName("iris/middleware/recaptcha.*", "iris.reCAPTCHA")
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
func init() {
|
||||
context.SetHandlerName("iris/middleware/recover.*", "Panic Recover")
|
||||
context.SetHandlerName("iris/middleware/recover.*", "iris.recover")
|
||||
}
|
||||
|
||||
func getRequestLogs(ctx context.Context) string {
|
||||
|
|
Loading…
Reference in New Issue
Block a user