-
Notifications
You must be signed in to change notification settings - Fork 5
/
router.go
131 lines (110 loc) · 3.34 KB
/
router.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
package oas
import (
"net/http"
"github.com/go-openapi/analysis"
"github.com/go-openapi/spec"
)
// Router routes requests based on OAS 2.0 spec operations.
type Router struct {
debugLog LogWriter
baseRouter BaseRouter
mws []Middleware
// serveSpec, if nonzero, makes router serve its spec.
serveSpec SpecHandlerType
}
// ServeHTTP implements http.Handler.
func (r Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
r.baseRouter.ServeHTTP(w, req)
}
// NewRouter returns a new Router.
func NewRouter(
sw *spec.Swagger,
handlers OperationHandlers,
options ...RouterOption,
) (Router, error) {
// Apply argument options.
router := Router{}
for _, o := range options {
o(&router)
}
// Default options
if router.debugLog == nil {
router.debugLog = func(format string, args ...interface{}) {}
}
if router.baseRouter == nil {
router.baseRouter = defaultBaseRouter()
}
// Router handles all the spec operations.
base := router.baseRouter
// Serve the specification itself if enabled.
if router.serveSpec != 0 {
var specHandler http.Handler
switch router.serveSpec {
case SpecHandlerTypeDynamic:
specHandler = DynamicSpecHandler(sw)
case SpecHandlerTypeStatic:
specHandler = StaticSpecHandler(sw)
}
base.Route(http.MethodGet, sw.BasePath, specHandler)
}
for method, pathOps := range analysis.New(sw).Operations() {
for path, op := range pathOps {
handler, ok := handlers[OperationID(op.ID)]
if !ok {
router.debugLog("oas: no handler registered for operation %s", op.ID)
continue
}
// Apply custom middleware before the operationIDMiddleware so
// they can use the OptionID.
for _, mwf := range router.mws {
handler = mwf(handler)
}
// Add all path parameters to operation parameters.
for _, pathParam := range sw.Paths.Paths[path].Parameters {
op.AddParam(&pathParam)
}
router.debugLog("oas: handle %s %s", method, sw.BasePath+path)
handler = newOperationMiddleware(op)(handler)
base.Route(method, sw.BasePath+path, handler)
}
}
return router, nil
}
// BaseRouter is an underlying router used in oas router.
// Any third-party router can be a BaseRouter by using adapter pattern.
type BaseRouter interface {
http.Handler
Route(method string, pathPattern string, handler http.Handler)
}
// LogWriter logs router operations that will be handled and what will be not
// during router creation. Useful for debugging.
type LogWriter func(format string, args ...interface{})
// RouterOption is an option for oas router.
type RouterOption func(*Router)
// DebugLog returns an option that sets a debug log for oas router.
// Debug log may help to see what router operations will be handled and what
// will be not.
func DebugLog(lw LogWriter) RouterOption {
return func(args *Router) {
args.debugLog = lw
}
}
// Base returns an option that sets a BaseRouter for oa2 router.
// It allows to plug-in your favorite router to the oas router.
func Base(br BaseRouter) RouterOption {
return func(args *Router) {
args.baseRouter = br
}
}
// Use returns an option that sets a middleware for router operations.
func Use(mw Middleware) RouterOption {
return func(args *Router) {
args.mws = append(args.mws, mw)
}
}
// ServeSpec returns an option that makes router serve its spec.
func ServeSpec(t SpecHandlerType) RouterOption {
return func(r *Router) {
r.serveSpec = t
}
}