-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp.go
More file actions
126 lines (110 loc) · 3.18 KB
/
Copy pathhttp.go
File metadata and controls
126 lines (110 loc) · 3.18 KB
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
package httper
import (
"fmt"
"net/http"
"path"
"reflect"
"runtime"
)
type Middleware func(next http.Handler) http.Handler
type ServeMux struct {
mux *http.ServeMux
// root handle
IsBreakRootRouter bool
NotFoundHandler http.Handler
// group
routers map[string]string
groupPrefix string
isRootGroup bool
middlewares []Middleware
}
func NewServeMux() *ServeMux {
return &ServeMux{
mux: http.NewServeMux(),
// root handle
IsBreakRootRouter: true,
NotFoundHandler: http.NotFoundHandler(),
// group
routers: make(map[string]string),
isRootGroup: true,
middlewares: make([]Middleware, 0),
}
}
func (sm *ServeMux) Use(middleware ...Middleware) {
sm.middlewares = append(sm.middlewares, middleware...)
}
func (sm *ServeMux) Group(prefix string) *ServeMux {
middlewares := make([]Middleware, 0)
// add middlewares of parent serve mux,but not root serve mux
if !sm.isRootGroup {
middlewares = append(middlewares, sm.middlewares...)
}
newServeMux := &ServeMux{
mux: sm.mux,
IsBreakRootRouter: sm.IsBreakRootRouter,
NotFoundHandler: sm.NotFoundHandler,
routers: sm.routers,
groupPrefix: sm.groupPrefix + prefix,
isRootGroup: false,
middlewares: middlewares,
}
return newServeMux
}
func (sm *ServeMux) GET(router string, handler http.Handler) {
sm.registerRouter(http.MethodGet, router, handler)
}
func (sm *ServeMux) POST(router string, handler http.Handler) {
sm.registerRouter(http.MethodPost, router, handler)
}
func (sm *ServeMux) PUT(router string, handler http.Handler) {
sm.registerRouter(http.MethodPut, router, handler)
}
func (sm *ServeMux) DELETE(router string, handler http.Handler) {
sm.registerRouter(http.MethodDelete, router, handler)
}
func (sm *ServeMux) registerRouter(method string, router string, handler http.Handler) {
// use middlewares of not root serve mux
if !sm.isRootGroup {
handler = sm.useMiddlewares(handler, sm.middlewares...)
}
router = fmt.Sprintf("%s %s%s", method, sm.groupPrefix, router)
sm.routers[router] = funcName(handler)
sm.mux.Handle(router, handler)
}
func (sm *ServeMux) Routes() map[string]string {
return sm.routers
}
func (sm *ServeMux) Start(addr string) error {
var handler http.Handler
handler = sm.mux
if sm.IsBreakRootRouter {
handler = sm.breakRootRouterHandler(sm.mux)
}
// use middlewares of the root serve mux
handler = sm.useMiddlewares(handler, sm.middlewares...)
return http.ListenAndServe(addr, handler)
}
func (sm *ServeMux) breakRootRouterHandler(mux *http.ServeMux) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, pattern := mux.Handler(r)
rootRouter := fmt.Sprintf("%s %s", r.Method, "/")
// break root pattern
if pattern == rootRouter && r.URL.Path != "/" {
sm.NotFoundHandler.ServeHTTP(w, r)
return
}
mux.ServeHTTP(w, r)
})
}
func (sm *ServeMux) useMiddlewares(handler http.Handler, middlewares ...Middleware) http.Handler {
l := len(sm.middlewares) - 1
// use middlewares reversely
for i := l; i >= 0; i-- {
handler = middlewares[i](handler)
}
return handler
}
func funcName(fn any) string {
n := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
return path.Base(n)
}