Skip to content

Commit 66e3c26

Browse files
committed
new app.MiddlewareExists method
1 parent 4eb7705 commit 66e3c26

File tree

8 files changed

+125
-17
lines changed

8 files changed

+125
-17
lines changed

HISTORY.md

+36
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,42 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
2424

2525
Changes apply to `main` branch.
2626

27+
- New `Application/Party.MiddlewareExists(handlerNameOrHandler)` method added, example:
28+
29+
```go
30+
package main
31+
32+
import (
33+
"fmt"
34+
35+
"github.com/kataras/iris/v12"
36+
"github.com/kataras/iris/v12/x/errors"
37+
)
38+
39+
func main() {
40+
app := iris.New()
41+
42+
app.UseRouter(errors.RecoveryHandler)
43+
44+
if app.MiddlewareExists(errors.RecoveryHandler) { // <- HERE.
45+
fmt.Println("errors.RecoveryHandler exists")
46+
}
47+
// OR:
48+
// if app.MiddlewareExists("iris.errors.recover") {
49+
// fmt.Println("Iris.Errors.Recovery exists")
50+
// }
51+
52+
app.Get("/", indexHandler)
53+
54+
app.Listen(":8080")
55+
}
56+
57+
func indexHandler(ctx iris.Context) {
58+
panic("an error here")
59+
ctx.HTML("<h1>Index</h1>")
60+
}
61+
62+
```
2763
- New `x/errors.Intercept(func(ctx iris.Context, req *CreateRequest, resp *CreateResponse) error{ ... })` package-level function.
2864

2965
```go

context/handler.go

+48-14
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ var (
3838
"iris.logger",
3939
"iris.rate",
4040
"iris.methodoverride",
41+
"iris.errors.recover",
4142
}
4243
)
4344

@@ -111,20 +112,6 @@ type Handler = func(*Context)
111112
// See `Handler` for more.
112113
type Handlers = []Handler
113114

114-
// CopyHandlers returns a copy of "handlers" Handlers slice.
115-
func CopyHandlers(handlers []Handler) Handlers {
116-
handlersCp := make([]Handler, 0, len(handlers))
117-
for _, handler := range handlers {
118-
if handler == nil {
119-
continue
120-
}
121-
122-
handlersCp = append(handlersCp, handler)
123-
}
124-
125-
return handlersCp
126-
}
127-
128115
func valueOf(v interface{}) reflect.Value {
129116
if val, ok := v.(reflect.Value); ok {
130117
return val
@@ -378,3 +365,50 @@ reg:
378365

379366
return h1
380367
}
368+
369+
// CopyHandlers returns a copy of "handlers" Handlers slice.
370+
func CopyHandlers(handlers Handlers) Handlers {
371+
handlersCp := make(Handlers, 0, len(handlers))
372+
for _, handler := range handlers {
373+
if handler == nil {
374+
continue
375+
}
376+
377+
handlersCp = append(handlersCp, handler)
378+
}
379+
380+
return handlersCp
381+
}
382+
383+
// HandlerExists reports whether a handler exists in the "handlers" slice.
384+
func HandlerExists(handlers Handlers, handlerNameOrFunc any) bool {
385+
if handlerNameOrFunc == nil {
386+
return false
387+
}
388+
389+
var matchHandler func(any) bool
390+
391+
switch v := handlerNameOrFunc.(type) {
392+
case string:
393+
matchHandler = func(handler any) bool {
394+
return HandlerName(handler) == v
395+
}
396+
case Handler:
397+
handlerName := HandlerName(v)
398+
matchHandler = func(handler any) bool {
399+
return HandlerName(handler) == handlerName
400+
}
401+
default:
402+
matchHandler = func(handler any) bool {
403+
return reflect.TypeOf(handler) == reflect.TypeOf(v)
404+
}
405+
}
406+
407+
for _, handler := range handlers {
408+
if matchHandler(handler) {
409+
return true
410+
}
411+
}
412+
413+
return false
414+
}

core/router/api_builder.go

+20
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,26 @@ func (api *APIBuilder) DoneGlobal(handlers ...context.Handler) {
13701370
api.doneGlobalHandlers = append(api.doneGlobalHandlers, handlers...)
13711371
}
13721372

1373+
// MiddlewareExists reports whether the given handler exists in the middleware chain.
1374+
func (api *APIBuilder) MiddlewareExists(handlerNameOrFunc any) bool {
1375+
if handlerNameOrFunc == nil {
1376+
return false
1377+
}
1378+
1379+
var handlers context.Handlers
1380+
1381+
if filter, ok := api.routerFilters[api]; ok {
1382+
handlers = append(handlers, filter.Handlers...)
1383+
}
1384+
1385+
handlers = append(handlers, api.middleware...)
1386+
handlers = append(handlers, api.doneHandlers...)
1387+
handlers = append(handlers, api.beginGlobalHandlers...)
1388+
handlers = append(handlers, api.doneGlobalHandlers...)
1389+
1390+
return context.HandlerExists(handlers, handlerNameOrFunc)
1391+
}
1392+
13731393
// RemoveHandler deletes a handler from begin and done handlers
13741394
// based on its name or the handler pc function.
13751395
// Note that UseGlobal and DoneGlobal handlers cannot be removed

core/router/party.go

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

iris_guide.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"strings"
55
"time"
66

7+
"github.com/kataras/iris/v12/context"
78
"github.com/kataras/iris/v12/core/router"
89

910
"github.com/kataras/iris/v12/middleware/cors"
@@ -508,8 +509,13 @@ func (s *step7) Build() *Application {
508509
app.SetContextErrorHandler(errors.DefaultContextErrorHandler)
509510
app.Macros().SetErrorHandler(errors.DefaultPathParameterTypeErrorHandler)
510511

511-
app.UseRouter(recover.New())
512-
app.UseRouter(s.step6.step5.routerMiddlewares...)
512+
routeFilters := s.step6.step5.routerMiddlewares
513+
if !context.HandlerExists(routeFilters, errors.RecoveryHandler) {
514+
// If not errors.RecoveryHandler registered, then use the default one.
515+
app.UseRouter(recover.New())
516+
}
517+
518+
app.UseRouter(routeFilters...)
513519
app.UseRouter(func(ctx Context) {
514520
ctx.Header("Server", "Iris")
515521
if dev := s.step6.step5.step4.step3.developer; dev != "" {

middleware/recover/recover.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func init() {
14-
context.SetHandlerName("iris/middleware/recover.*", "iris.recover")
14+
context.SetHandlerName("iris/middleware/recover.*", "iris.recover") // this name won't work because New() is a function that returns a handler.
1515
}
1616

1717
// New returns a new recovery middleware,

x/errors/errors.go

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
"log/slog"
78
"net/http"
89

910
"github.com/kataras/iris/v12/context"
@@ -20,6 +21,11 @@ type LogErrorFunc = func(ctx *context.Context, err error)
2021
// LogError can be modified to customize the way an error is logged to the server (most common: internal server errors, database errors et.c.).
2122
// Can be used to customize the error logging, e.g. using Sentry (cloud-based error console).
2223
var LogError LogErrorFunc = func(ctx *context.Context, err error) {
24+
if ctx == nil {
25+
slog.Error(err.Error())
26+
return
27+
}
28+
2329
ctx.Application().Logger().Error(err)
2430
}
2531

x/errors/handlers.go

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import (
1313
"golang.org/x/exp/constraints"
1414
)
1515

16+
func init() {
17+
context.SetHandlerName("iris/x/errors.RecoveryHandler.*", "iris.errors.recover")
18+
}
19+
1620
// RecoveryHandler is a middleware which recovers from panics and sends an appropriate error response
1721
// to the logger and the client.
1822
func RecoveryHandler(ctx *context.Context) {

0 commit comments

Comments
 (0)