new app.MiddlewareExists method

This commit is contained in:
Gerasimos (Makis) Maropoulos 2024-01-21 17:16:59 +02:00
parent 4eb7705fae
commit 66e3c26efe
No known key found for this signature in database
GPG Key ID: B9839E9CD30B7B6B
8 changed files with 125 additions and 17 deletions

View File

@ -24,6 +24,42 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
Changes apply to `main` branch.
- New `Application/Party.MiddlewareExists(handlerNameOrHandler)` method added, example:
```go
package main
import (
"fmt"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/x/errors"
)
func main() {
app := iris.New()
app.UseRouter(errors.RecoveryHandler)
if app.MiddlewareExists(errors.RecoveryHandler) { // <- HERE.
fmt.Println("errors.RecoveryHandler exists")
}
// OR:
// if app.MiddlewareExists("iris.errors.recover") {
// fmt.Println("Iris.Errors.Recovery exists")
// }
app.Get("/", indexHandler)
app.Listen(":8080")
}
func indexHandler(ctx iris.Context) {
panic("an error here")
ctx.HTML("<h1>Index</h1>")
}
```
- New `x/errors.Intercept(func(ctx iris.Context, req *CreateRequest, resp *CreateResponse) error{ ... })` package-level function.
```go

View File

@ -38,6 +38,7 @@ var (
"iris.logger",
"iris.rate",
"iris.methodoverride",
"iris.errors.recover",
}
)
@ -111,20 +112,6 @@ type Handler = func(*Context)
// See `Handler` for more.
type Handlers = []Handler
// CopyHandlers returns a copy of "handlers" Handlers slice.
func CopyHandlers(handlers []Handler) Handlers {
handlersCp := make([]Handler, 0, len(handlers))
for _, handler := range handlers {
if handler == nil {
continue
}
handlersCp = append(handlersCp, handler)
}
return handlersCp
}
func valueOf(v interface{}) reflect.Value {
if val, ok := v.(reflect.Value); ok {
return val
@ -378,3 +365,50 @@ reg:
return h1
}
// CopyHandlers returns a copy of "handlers" Handlers slice.
func CopyHandlers(handlers Handlers) Handlers {
handlersCp := make(Handlers, 0, len(handlers))
for _, handler := range handlers {
if handler == nil {
continue
}
handlersCp = append(handlersCp, handler)
}
return handlersCp
}
// HandlerExists reports whether a handler exists in the "handlers" slice.
func HandlerExists(handlers Handlers, handlerNameOrFunc any) bool {
if handlerNameOrFunc == nil {
return false
}
var matchHandler func(any) bool
switch v := handlerNameOrFunc.(type) {
case string:
matchHandler = func(handler any) bool {
return HandlerName(handler) == v
}
case Handler:
handlerName := HandlerName(v)
matchHandler = func(handler any) bool {
return HandlerName(handler) == handlerName
}
default:
matchHandler = func(handler any) bool {
return reflect.TypeOf(handler) == reflect.TypeOf(v)
}
}
for _, handler := range handlers {
if matchHandler(handler) {
return true
}
}
return false
}

View File

@ -1370,6 +1370,26 @@ func (api *APIBuilder) DoneGlobal(handlers ...context.Handler) {
api.doneGlobalHandlers = append(api.doneGlobalHandlers, handlers...)
}
// MiddlewareExists reports whether the given handler exists in the middleware chain.
func (api *APIBuilder) MiddlewareExists(handlerNameOrFunc any) bool {
if handlerNameOrFunc == nil {
return false
}
var handlers context.Handlers
if filter, ok := api.routerFilters[api]; ok {
handlers = append(handlers, filter.Handlers...)
}
handlers = append(handlers, api.middleware...)
handlers = append(handlers, api.doneHandlers...)
handlers = append(handlers, api.beginGlobalHandlers...)
handlers = append(handlers, api.doneGlobalHandlers...)
return context.HandlerExists(handlers, handlerNameOrFunc)
}
// RemoveHandler deletes a handler from begin and done handlers
// based on its name or the handler pc function.
// Note that UseGlobal and DoneGlobal handlers cannot be removed

View File

@ -234,6 +234,8 @@ type Party interface {
// Done appends to the very end, Handler(s) to the current Party's routes and child routes.
// The difference from .Use is that this/or these Handler(s) are being always running last.
Done(handlers ...context.Handler)
// MiddlewareExists reports whether the given handler exists in the middleware chain.
MiddlewareExists(handlerNameOrFunc any) bool
// RemoveHandler deletes a handler from begin and done handlers
// based on its name or the handler pc function.
//

View File

@ -4,6 +4,7 @@ import (
"strings"
"time"
"github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/core/router"
"github.com/kataras/iris/v12/middleware/cors"
@ -508,8 +509,13 @@ func (s *step7) Build() *Application {
app.SetContextErrorHandler(errors.DefaultContextErrorHandler)
app.Macros().SetErrorHandler(errors.DefaultPathParameterTypeErrorHandler)
app.UseRouter(recover.New())
app.UseRouter(s.step6.step5.routerMiddlewares...)
routeFilters := s.step6.step5.routerMiddlewares
if !context.HandlerExists(routeFilters, errors.RecoveryHandler) {
// If not errors.RecoveryHandler registered, then use the default one.
app.UseRouter(recover.New())
}
app.UseRouter(routeFilters...)
app.UseRouter(func(ctx Context) {
ctx.Header("Server", "Iris")
if dev := s.step6.step5.step4.step3.developer; dev != "" {

View File

@ -11,7 +11,7 @@ import (
)
func init() {
context.SetHandlerName("iris/middleware/recover.*", "iris.recover")
context.SetHandlerName("iris/middleware/recover.*", "iris.recover") // this name won't work because New() is a function that returns a handler.
}
// New returns a new recovery middleware,

View File

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"log/slog"
"net/http"
"github.com/kataras/iris/v12/context"
@ -20,6 +21,11 @@ type LogErrorFunc = func(ctx *context.Context, err error)
// LogError can be modified to customize the way an error is logged to the server (most common: internal server errors, database errors et.c.).
// Can be used to customize the error logging, e.g. using Sentry (cloud-based error console).
var LogError LogErrorFunc = func(ctx *context.Context, err error) {
if ctx == nil {
slog.Error(err.Error())
return
}
ctx.Application().Logger().Error(err)
}

View File

@ -13,6 +13,10 @@ import (
"golang.org/x/exp/constraints"
)
func init() {
context.SetHandlerName("iris/x/errors.RecoveryHandler.*", "iris.errors.recover")
}
// RecoveryHandler is a middleware which recovers from panics and sends an appropriate error response
// to the logger and the client.
func RecoveryHandler(ctx *context.Context) {