-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathhandler.go
159 lines (139 loc) · 4.88 KB
/
handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package iris
import (
"net/http"
"github.com/kataras/go-errors"
)
// errHandler returns na error with message: 'Passed argument is not func(*Context) neither an object which implements the iris.Default.Handler with Serve(ctx *Context)
// It seems to be a +type Points to: +pointer.'
var errHandler = errors.New(`
Passed argument is not an iris.Handler (or func(*iris.Context)) neither one of these types:
- http.Handler
- func(w http.ResponseWriter, r *http.Request)
- func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)
---------------------------------------------------------------------
It seems to be a %T points to: %v`)
type (
// Handler the main Iris Handler interface.
Handler interface {
Serve(ctx *Context) // iris-specific
}
// HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
HandlerFunc func(*Context)
// Middleware is just a slice of Handler []func(c *Context)
Middleware []Handler
)
// Serve implements the Handler, is like ServeHTTP but for Iris
func (h HandlerFunc) Serve(ctx *Context) {
h(ctx)
}
// ToNativeHandler converts an iris handler to http.Handler
func ToNativeHandler(s *Framework, h Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
s.Context.Run(w, r, func(ctx *Context) {
h.Serve(ctx)
})
})
}
// ToHandler converts different style of handlers that you
// used to use (usually with third-party net/http middleware) to an iris.HandlerFunc.
//
// Supported types:
// - .ToHandler(h http.Handler)
// - .ToHandler(func(w http.ResponseWriter, r *http.Request))
// - .ToHandler(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc))
func ToHandler(handler interface{}) HandlerFunc {
switch handler.(type) {
case HandlerFunc:
{
//
//it's already an iris handler
//
return handler.(HandlerFunc)
}
case http.Handler:
//
// handlerFunc.ServeHTTP(w,r)
//
{
h := handler.(http.Handler)
return func(ctx *Context) {
h.ServeHTTP(ctx.ResponseWriter, ctx.Request)
}
}
case func(http.ResponseWriter, *http.Request):
{
//
// handlerFunc(w,r)
//
return ToHandler(http.HandlerFunc(handler.(func(http.ResponseWriter, *http.Request))))
}
case func(http.ResponseWriter, *http.Request, http.HandlerFunc):
{
//
// handlerFunc(w,r, http.HandlerFunc)
//
return toHandlerNextHTTPHandlerFunc(handler.(func(http.ResponseWriter, *http.Request, http.HandlerFunc)))
}
default:
{
//
// No valid handler passed
//
panic(errHandler.Format(handler, handler))
}
}
}
func toHandlerNextHTTPHandlerFunc(h func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)) HandlerFunc {
return HandlerFunc(func(ctx *Context) {
// take the next handler in route's chain
nextIrisHandler := ctx.NextHandler()
if nextIrisHandler != nil {
executed := false // we need to watch this in order to StopExecution from all next handlers
// if this next handler is not executed by the third-party net/http next-style middleware.
nextHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
nextIrisHandler.Serve(ctx)
executed = true
})
h(ctx.ResponseWriter, ctx.Request, nextHandler)
// after third-party middleware's job:
if executed {
// if next is executed then increment the ctx.Pos manually
// in order to the next handler not to be executed twice.
ctx.Pos++
} else {
// otherwise StopExecution from all next handlers.
ctx.StopExecution()
}
return
}
// if not next handler found then this is not a 'valid' middleware but
// some middleware may don't care about next,
// so we just execute the handler with an empty net.
h(ctx.ResponseWriter, ctx.Request, http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}))
})
}
// convertToHandlers just make []HandlerFunc to []Handler, although HandlerFunc and Handler are the same
// we need this on some cases we explicit want a interface Handler, it is useless for users.
func convertToHandlers(handlersFn []HandlerFunc) []Handler {
hlen := len(handlersFn)
mlist := make([]Handler, hlen)
for i := 0; i < hlen; i++ {
mlist[i] = Handler(handlersFn[i])
}
return mlist
}
// joinMiddleware uses to create a copy of all middleware and return them in order to use inside the node
func joinMiddleware(middleware1 Middleware, middleware2 Middleware) Middleware {
nowLen := len(middleware1)
totalLen := nowLen + len(middleware2)
// create a new slice of middleware in order to store all handlers, the already handlers(middleware) and the new
newMiddleware := make(Middleware, totalLen)
//copy the already middleware to the just created
copy(newMiddleware, middleware1)
//start from there we finish, and store the new middleware too
copy(newMiddleware[nowLen:], middleware2)
return newMiddleware
}