mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 02:17:05 +00:00
error handlers per party: log those routes too and all test cases paased
need cleanup though Former-commit-id: 6b0c18e38b58af2388015c7cf1af9cc43d7d35d3
This commit is contained in:
@@ -981,23 +981,11 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
|
|||||||
func (api *APIBuilder) OnErrorCode(statusCode int, handlers ...context.Handler) {
|
func (api *APIBuilder) OnErrorCode(statusCode int, handlers ...context.Handler) {
|
||||||
// TODO: think a stable way for that and document it so end-developers
|
// TODO: think a stable way for that and document it so end-developers
|
||||||
// not be suprised. Many feature requests in the past asked for that per-party error handlers.
|
// not be suprised. Many feature requests in the past asked for that per-party error handlers.
|
||||||
|
api.handle(statusCode, "", "/", handlers...)
|
||||||
|
|
||||||
if api.relativePath != "/" {
|
if api.relativePath != "/" {
|
||||||
api.handle(statusCode, "", "/{tail:path}", handlers...)
|
api.handle(statusCode, "", "/{tail:path}", handlers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
api.handle(statusCode, "", "/", handlers...)
|
|
||||||
|
|
||||||
// if api.relativePath != "/" /* root is OK, no need to wildcard, see handler.go */ &&
|
|
||||||
// !strings.HasSuffix(api.relativePath, "}") /* and not /users/{id:int} */ {
|
|
||||||
// // We need to register the /users and the /users/{tail:path},
|
|
||||||
// api.handle(statusCode, "", "/{tail:path}", handlers...)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if strings.HasSuffix(api.relativePath, "/") {
|
|
||||||
// api.handle(statusCode, "", "/", handlers...)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// api.handle(statusCode, "", "/{tail:path}", handlers...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnAnyErrorCode registers a handler which called when error status code written.
|
// OnAnyErrorCode registers a handler which called when error status code written.
|
||||||
@@ -1058,25 +1046,32 @@ func getCaller() (string, int) {
|
|||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
for {
|
for {
|
||||||
frame, more := frames.Next()
|
frame, more := frames.Next()
|
||||||
file := frame.File
|
file := filepath.ToSlash(frame.File)
|
||||||
|
|
||||||
if strings.Contains(file, "src/testing/testing.go") {
|
if !strings.Contains(file, "_test.go") {
|
||||||
|
if strings.Contains(file, "/kataras/iris") && !strings.Contains(file, "kataras/iris/_examples") && !strings.Contains(file, "iris-contrib/examples") {
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(file, "go/src/runtime/") {
|
||||||
|
if !more {
|
||||||
|
break
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(file, "/kataras/iris") ||
|
if relFile, err := filepath.Rel(wd, file); err == nil {
|
||||||
strings.Contains(file, "_examples") ||
|
if !strings.HasPrefix(relFile, "..") {
|
||||||
strings.Contains(file, "examples") {
|
// Only if it's relative to this path, not parent.
|
||||||
if relFile, err := filepath.Rel(wd, file); err == nil {
|
|
||||||
file = "./" + relFile
|
file = "./" + relFile
|
||||||
}
|
}
|
||||||
|
|
||||||
return file, frame.Line
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !more {
|
return file, frame.Line
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "???", 0
|
return "???", 0
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
|||||||
routes []*Route
|
routes []*Route
|
||||||
}
|
}
|
||||||
|
|
||||||
allMethods := append(AllMethods, MethodNone)
|
allMethods := append(AllMethods, []string{MethodNone, ""}...)
|
||||||
methodRoutes := make([]MethodRoutes, 0, len(allMethods))
|
methodRoutes := make([]MethodRoutes, 0, len(allMethods))
|
||||||
|
|
||||||
for _, method := range allMethods {
|
for _, method := range allMethods {
|
||||||
@@ -246,6 +246,9 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
|||||||
fmt.Fprint(logger.Printer, ", ")
|
fmt.Fprint(logger.Printer, ", ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if m.method == "" {
|
||||||
|
m.method = "ERROR"
|
||||||
|
}
|
||||||
fmt.Fprintf(logger.Printer, "%d ", len(m.routes))
|
fmt.Fprintf(logger.Printer, "%d ", len(m.routes))
|
||||||
pio.WriteRich(logger.Printer, m.method, traceMethodColor(m.method))
|
pio.WriteRich(logger.Printer, m.method, traceMethodColor(m.method))
|
||||||
}
|
}
|
||||||
@@ -459,6 +462,16 @@ func (h *routerHandler) FireErrorCode(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n != nil {
|
if n != nil {
|
||||||
|
// Note: handlers can contain macro filters here,
|
||||||
|
// they are registered as error handlers, see macro/handler.go#42.
|
||||||
|
|
||||||
|
// fmt.Println("Error Handlers")
|
||||||
|
// for _, h := range n.Handlers {
|
||||||
|
|
||||||
|
// f, l := context.HandlerFileLine(h)
|
||||||
|
// fmt.Printf("%s: %s:%d\n", ctx.Path(), f, l)
|
||||||
|
// }
|
||||||
|
|
||||||
// fire this http status code's error handlers chain.
|
// fire this http status code's error handlers chain.
|
||||||
|
|
||||||
// ctx.StopExecution() // not uncomment this, is here to remember why to.
|
// ctx.StopExecution() // not uncomment this, is here to remember why to.
|
||||||
|
|||||||
@@ -386,7 +386,7 @@ func traceMethodColor(method string) int {
|
|||||||
return color
|
return color
|
||||||
}
|
}
|
||||||
|
|
||||||
return pio.Black
|
return 131 // for error handlers, of "ERROR [%STATUSCODE]"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace prints some debug info about the Route to the "w".
|
// Trace prints some debug info about the Route to the "w".
|
||||||
@@ -397,13 +397,18 @@ func traceMethodColor(method string) int {
|
|||||||
// * @second_handler ...
|
// * @second_handler ...
|
||||||
// If route and handler line:number locations are equal then the second is ignored.
|
// If route and handler line:number locations are equal then the second is ignored.
|
||||||
func (r *Route) Trace(w io.Writer) {
|
func (r *Route) Trace(w io.Writer) {
|
||||||
|
method := r.Method
|
||||||
|
if method == "" {
|
||||||
|
method = fmt.Sprintf("%d", r.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
// Color the method.
|
// Color the method.
|
||||||
color := traceMethodColor(r.Method)
|
color := traceMethodColor(method)
|
||||||
|
|
||||||
// @method: @path
|
// @method: @path
|
||||||
// space := strings.Repeat(" ", len(http.MethodConnect)-len(r.Method))
|
// space := strings.Repeat(" ", len(http.MethodConnect)-len(method))
|
||||||
// s := fmt.Sprintf("%s: %s", pio.Rich(r.Method, color), path)
|
// s := fmt.Sprintf("%s: %s", pio.Rich(method, color), path)
|
||||||
pio.WriteRich(w, r.Method, color)
|
pio.WriteRich(w, method, color)
|
||||||
|
|
||||||
path := r.Tmpl().Src
|
path := r.Tmpl().Src
|
||||||
if path == "" {
|
if path == "" {
|
||||||
@@ -415,7 +420,7 @@ func (r *Route) Trace(w io.Writer) {
|
|||||||
// (@description)
|
// (@description)
|
||||||
description := r.Description
|
description := r.Description
|
||||||
if description == "" {
|
if description == "" {
|
||||||
if r.Method == MethodNone {
|
if method == MethodNone {
|
||||||
description = "offline"
|
description = "offline"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,27 +89,30 @@ func TestPartyOnErrorCode(t *testing.T) {
|
|||||||
|
|
||||||
app.Get("/path", h)
|
app.Get("/path", h)
|
||||||
|
|
||||||
h := func(ctx iris.Context) { ctx.WriteString(ctx.Path()) }
|
|
||||||
usersResponse := "users: method allowed"
|
usersResponse := "users: method allowed"
|
||||||
|
|
||||||
users := app.Party("/users")
|
users := app.Party("/users")
|
||||||
users.OnErrorCode(iris.StatusMethodNotAllowed, func(ctx iris.Context) {
|
users.OnErrorCode(iris.StatusMethodNotAllowed, func(ctx iris.Context) {
|
||||||
ctx.WriteString(usersResponse)
|
ctx.WriteString(usersResponse)
|
||||||
})
|
})
|
||||||
users.Get("/", h)
|
users.Get("/", h)
|
||||||
|
write400 := func(ctx iris.Context) { ctx.StatusCode(iris.StatusBadRequest) }
|
||||||
// test setting the error code from a handler.
|
// test setting the error code from a handler.
|
||||||
users.Get("/badrequest", func(ctx iris.Context) { ctx.StatusCode(iris.StatusBadRequest) })
|
users.Get("/badrequest", write400)
|
||||||
|
|
||||||
usersuserResponse := "users:user: method allowed"
|
usersuserResponse := "users:user: method allowed"
|
||||||
user := users.Party("/{id:int}")
|
user := users.Party("/{id:int}")
|
||||||
user.OnErrorCode(iris.StatusMethodNotAllowed, func(ctx iris.Context) {
|
user.OnErrorCode(iris.StatusMethodNotAllowed, func(ctx iris.Context) {
|
||||||
ctx.WriteString(usersuserResponse)
|
ctx.WriteString(usersuserResponse)
|
||||||
})
|
})
|
||||||
// usersuserNotFoundResponse := "users:user: not found"
|
usersuserNotFoundResponse := "users:user: not found"
|
||||||
// user.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
|
user.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
|
||||||
// ctx.WriteString(usersuserNotFoundResponse)
|
ctx.WriteString(usersuserNotFoundResponse)
|
||||||
// })
|
})
|
||||||
user.Get("/", h)
|
user.Get("/", h)
|
||||||
|
user.Get("/ab/badrequest", write400)
|
||||||
|
|
||||||
|
friends := users.Party("/friends")
|
||||||
|
friends.Get("/{id:int}", h)
|
||||||
|
|
||||||
e := httptest.New(t, app)
|
e := httptest.New(t, app)
|
||||||
|
|
||||||
@@ -125,10 +128,12 @@ func TestPartyOnErrorCode(t *testing.T) {
|
|||||||
|
|
||||||
e.GET("/users/42").Expect().Status(iris.StatusOK).
|
e.GET("/users/42").Expect().Status(iris.StatusOK).
|
||||||
Body().Equal("/users/42")
|
Body().Equal("/users/42")
|
||||||
// e.GET("/users/ab").Expect().Status(iris.StatusNotFound).Body().Equal(usersuserNotFoundResponse)
|
e.GET("/users/ab").Expect().Status(iris.StatusNotFound).Body().Equal(usersuserNotFoundResponse)
|
||||||
|
// inherit the parent.
|
||||||
|
e.GET("/users/42/friends/dsa").Expect().Status(iris.StatusNotFound).Body().Equal(usersuserNotFoundResponse)
|
||||||
|
|
||||||
// if not registered to the party, then the root is taking action.
|
// if not registered to the party, then the root is taking action.
|
||||||
e.GET("/users/ab/cd").Expect().Status(iris.StatusNotFound).Body().Equal(globalNotFoundResponse)
|
e.GET("/users/42/ab/badrequest").Expect().Status(iris.StatusBadRequest).Body().Equal(http.StatusText(iris.StatusBadRequest))
|
||||||
|
|
||||||
// if not registered to the party, and not in root, then just write the status text (fallback behavior)
|
// if not registered to the party, and not in root, then just write the status text (fallback behavior)
|
||||||
e.GET("/users/badrequest").Expect().Status(iris.StatusBadRequest).
|
e.GET("/users/badrequest").Expect().Status(iris.StatusBadRequest).
|
||||||
|
|||||||
@@ -41,7 +41,10 @@ func newSource(fn reflect.Value) Source {
|
|||||||
|
|
||||||
wd, _ := os.Getwd()
|
wd, _ := os.Getwd()
|
||||||
if relFile, err := filepath.Rel(wd, callerFileName); err == nil {
|
if relFile, err := filepath.Rel(wd, callerFileName); err == nil {
|
||||||
callerFileName = "./" + relFile
|
if !strings.HasPrefix(relFile, "..") {
|
||||||
|
// Only if it's relative to this path, not parent.
|
||||||
|
callerFileName = "./" + relFile
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Source{
|
return Source{
|
||||||
|
|||||||
@@ -39,11 +39,17 @@ func MakeHandler(tmpl macro.Template) context.Handler {
|
|||||||
|
|
||||||
return func(ctx context.Context) {
|
return func(ctx context.Context) {
|
||||||
if !filter(ctx) {
|
if !filter(ctx) {
|
||||||
ctx.StopExecution()
|
if ctx.GetCurrentRoute().StatusErrorCode() == ctx.GetStatusCode() {
|
||||||
|
ctx.Next()
|
||||||
|
} else {
|
||||||
|
ctx.StopExecution()
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if all passed, just continue.
|
// if all passed or the next is the registered error handler to handle this status code,
|
||||||
|
// just continue.
|
||||||
ctx.Next()
|
ctx.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user