-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathcore.go
172 lines (146 loc) · 4.42 KB
/
core.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
160
161
162
163
164
165
166
167
168
169
170
171
172
package ucon
import (
"context"
"fmt"
"net/http"
"strings"
)
// DefaultMux is the default ServeMux in ucon.
var DefaultMux = NewServeMux()
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
mux := &ServeMux{
router: &Router{},
}
mux.router.mux = mux
return mux
}
// ServeMux is an HTTP request multiplexer.
type ServeMux struct {
Debug bool
router *Router
middlewares []MiddlewareFunc
plugins []*pluginContainer
}
// MiddlewareFunc is an adapter to hook middleware processing.
// Middleware works with 1 request.
type MiddlewareFunc func(b *Bubble) error
// Middleware can append Middleware to ServeMux.
func (m *ServeMux) Middleware(f MiddlewareFunc) {
m.middlewares = append(m.middlewares, f)
}
// Plugin can append Plugin to ServeMux.
func (m *ServeMux) Plugin(plugin interface{}) {
p, ok := plugin.(*pluginContainer)
if !ok {
p = &pluginContainer{base: plugin}
}
p.check()
m.plugins = append(m.plugins, p)
}
// Prepare the ServeMux.
// Plugin is not show affect to anything.
// This method is enabled plugins.
func (m *ServeMux) Prepare() {
for _, plugin := range m.plugins {
used := false
if sc := plugin.HandlersScanner(); sc != nil {
err := sc.HandlersScannerProcess(m, m.router.handlers)
if err != nil {
panic(err)
}
used = true
}
if !used {
panic(fmt.Sprintf("unused plugin: %#v", plugin))
}
}
}
// ServeHTTP dispatches request to the handler.
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// NOTE ucon内部のルーティングは一元的にこの関数から行う
// Handlerを細分化しhttp.ServeMuxに登録すると、OPTIONSのhandleがうまくできなくなる
// このため、Handlerはucon全体で1つとし、OPTIONSも通常のMethodと同じようにHandlerを設定し利用する
// OPTIONSを適切にhandleするため、全てのHandlerに特殊なHookを入れるよりマシである
m.router.ServeHTTP(w, r)
}
// ListenAndServe start accepts the client request.
func (m *ServeMux) ListenAndServe(addr string) error {
m.Prepare()
server := &http.Server{Addr: addr, Handler: m}
return server.ListenAndServe()
}
// Handle register the HandlerContainer for the given method & path to the ServeMux.
func (m *ServeMux) Handle(method string, path string, hc HandlerContainer) {
CheckFunction(hc.Handler())
pathTmpl := ParsePathTemplate(path)
methods := strings.Split(strings.ToUpper(method), ",")
for _, method := range methods {
rd := &RouteDefinition{
Method: method,
PathTemplate: pathTmpl,
HandlerContainer: hc,
}
m.router.addRoute(rd)
}
}
// HandleFunc register the handler function for the given method & path to the ServeMux.
func (m *ServeMux) HandleFunc(method string, path string, h interface{}) {
m.Handle(method, path, &handlerContainerImpl{
handler: h,
Context: background,
})
}
func (m *ServeMux) newBubble(c context.Context, w http.ResponseWriter, r *http.Request, rd *RouteDefinition) (*Bubble, error) {
b := &Bubble{
R: r,
W: w,
Context: c,
RequestHandler: rd.HandlerContainer,
}
err := b.init(m)
if err != nil {
return nil, err
}
return b, nil
}
// HandlerContainer is handler function container.
// and It has a ucon Context that make it possible communicate to Plugins.
type HandlerContainer interface {
Handler() interface{}
Context
}
type handlerContainerImpl struct {
handler interface{}
Context
}
func (hc *handlerContainerImpl) Handler() interface{} {
return hc.handler
}
// Orthodox middlewares enable to DefaultServeMux.
func Orthodox() {
DefaultMux.Middleware(ResponseMapper())
DefaultMux.Middleware(HTTPRWDI())
DefaultMux.Middleware(ContextDI())
DefaultMux.Middleware(RequestObjectMapper())
}
// Middleware can append Middleware to ServeMux.
func Middleware(f MiddlewareFunc) {
DefaultMux.Middleware(f)
}
// Plugin can append Plugin to ServeMux.
func Plugin(plugin interface{}) {
DefaultMux.Plugin(plugin)
}
// ListenAndServe start accepts the client request.
func ListenAndServe(addr string) {
DefaultMux.ListenAndServe(addr)
}
// Handle register the HandlerContainer for the given method & path to the ServeMux.
func Handle(method string, path string, hc HandlerContainer) {
DefaultMux.Handle(method, path, hc)
}
// HandleFunc register the handler function for the given method & path to the ServeMux.
func HandleFunc(method string, path string, h interface{}) {
DefaultMux.HandleFunc(method, path, h)
}