/
mux.go
133 lines (112 loc) · 3.37 KB
/
mux.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
// Package mux implements an HTTP domain-specific traffic multiplexer
// with built-in matchers and features for easy plugin composition and activable logic.
package mux
import (
c "gopkg.in/h2non/gentleman.v2/context"
"gopkg.in/h2non/gentleman.v2/middleware"
"gopkg.in/h2non/gentleman.v2/plugin"
)
// Mux is a HTTP request/response/error multiplexer who implements both
// middleware and plugin interfaces.
// It has been designed for easy plugin composition based on HTTP matchers/filters.
type Mux struct {
// Mux also implements a plugin capable interface.
*plugin.Layer
// Matchers stores a list of matcher functions.
Matchers []Matcher
// Middleware stores the multiplexer middleware layer.
Middleware middleware.Middleware
}
// New creates a new multiplexer with default settings.
func New() *Mux {
m := &Mux{Layer: plugin.New()}
m.Middleware = middleware.New()
handler := m.Handler()
m.DefaultHandler = handler
return m
}
// Match matches the give Context againts a list of matchers and
// returns `true` if all the matchers passed.
func (m *Mux) Match(ctx *c.Context) bool {
for _, matcher := range m.Matchers {
if !matcher(ctx) {
return false
}
}
return true
}
// AddMatcher adds a new matcher function in the current mumultiplexer matchers stack.
func (m *Mux) AddMatcher(matchers ...Matcher) *Mux {
m.Matchers = append(m.Matchers, matchers...)
return m
}
// Handler returns the function handler to match an incoming HTTP transacion
// and trigger the equivalent middleware phase.
func (m *Mux) Handler() c.HandlerFunc {
return func(ctx *c.Context, h c.Handler) {
if !m.Match(ctx) {
h.Next(ctx)
return
}
ctx = m.Middleware.Run(ctx.GetString("$phase"), ctx)
if ctx.Error != nil {
h.Error(ctx, ctx.Error)
return
}
if ctx.Stopped {
h.Stop(ctx)
return
}
h.Next(ctx)
}
}
// Use registers a new plugin in the middleware stack.
func (m *Mux) Use(p plugin.Plugin) *Mux {
m.Middleware.Use(p)
return m
}
// UseResponse registers a new response phase middleware handler.
func (m *Mux) UseResponse(fn c.HandlerFunc) *Mux {
m.Middleware.UseResponse(fn)
return m
}
// UseRequest registers a new request phase middleware handler.
func (m *Mux) UseRequest(fn c.HandlerFunc) *Mux {
m.Middleware.UseRequest(fn)
return m
}
// UseError registers a new error phase middleware handler.
func (m *Mux) UseError(fn c.HandlerFunc) *Mux {
m.Middleware.UseError(fn)
return m
}
// UseHandler registers a new error phase middleware handler.
func (m *Mux) UseHandler(phase string, fn c.HandlerFunc) *Mux {
m.Middleware.UseHandler(phase, fn)
return m
}
// UseParent attachs a parent middleware.
func (m *Mux) UseParent(parent middleware.Middleware) *Mux {
m.Middleware.UseParent(parent)
return m
}
// Flush flushes the plugins stack.
func (m *Mux) Flush() {
m.Middleware.Flush()
}
// SetStack sets the middleware plugin stack overriding the existent one.
func (m *Mux) SetStack(stack []plugin.Plugin) {
m.Middleware.SetStack(stack)
}
// GetStack gets the current middleware plugins stack.
func (m *Mux) GetStack() []plugin.Plugin {
return m.Middleware.GetStack()
}
// Clone creates a new Middleware instance based on the current one.
func (m *Mux) Clone() middleware.Middleware {
return m.Middleware.Clone()
}
// Run triggers the middleware call chain for the given phase.
func (m *Mux) Run(phase string, ctx *c.Context) *c.Context {
return m.Middleware.Run(phase, ctx)
}