1
1
package sandbox
2
2
3
3
import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "io"
4
7
"net/http"
5
8
9
+ "github.com/bmizerany/pat"
10
+ "github.com/dchest/uniuri"
6
11
"gopkg.in/vinxi/layer.v0"
7
12
"gopkg.in/vinxi/vinxi.v0"
8
13
)
@@ -16,9 +21,10 @@ type Options struct {
16
21
}
17
22
18
23
type Rule interface {
24
+ ID () string
19
25
Name () string
20
26
Description () string
21
- Options () Options
27
+ // Options() Options
22
28
JSONConfig () string
23
29
Match (* http.Request ) bool
24
30
}
@@ -28,12 +34,17 @@ type Scope struct {
28
34
rules []Rule
29
35
plugins * PluginLayer
30
36
37
+ ID string
31
38
Name string
32
39
Description string
33
40
}
34
41
35
- func NewScope () * Scope {
36
- return & Scope {Plugins : NewPluginLayer ()}
42
+ func NewScope (rules ... Rule ) * Scope {
43
+ return & Scope {ID : uniuri .New (), Name : "default" , plugins : NewPluginLayer (), rules : rules }
44
+ }
45
+
46
+ func (s * Scope ) UsePlugin (plugin Plugin ) {
47
+ s .plugins .Use (plugin )
37
48
}
38
49
39
50
func (s * Scope ) AddRule (rules ... Rule ) {
@@ -52,22 +63,23 @@ func (s *Scope) Enable() {
52
63
s .disabled = false
53
64
}
54
65
55
- func (s * Scope ) HandleHTTP (h http.Handler ) func (w http.ResponseWriter , req * http.Request ) {
56
- return func (w http.ResponseWriter , req * http.Request ) {
66
+ func (s * Scope ) HandleHTTP (h http.Handler ) func (http.ResponseWriter , * http.Request ) {
67
+ return func (w http.ResponseWriter , r * http.Request ) {
57
68
if s .disabled {
58
69
h .ServeHTTP (w , r )
59
70
return
60
71
}
61
72
62
- w .WriteHeader (502 )
63
- w .Write ([]byte ("bad request" ))
64
- }
65
- }
73
+ for _ , rule := range s .rules {
74
+ if ! rule .Match (r ) {
75
+ // Continue
76
+ h .ServeHTTP (w , r )
77
+ return
78
+ }
79
+ }
66
80
67
- func NewInstance (vinxi * vinxi.Vinxi ) * Instance {
68
- plugins := NewPluginLayer ()
69
- plugins .Register (vinxi )
70
- return & Instance {plugins : plugins , vinxi : vinxi }
81
+ s .plugins .Run (w , r , h )
82
+ }
71
83
}
72
84
73
85
type Manager struct {
@@ -82,17 +94,127 @@ func Manage(instance *vinxi.Vinxi) *Manager {
82
94
return m
83
95
}
84
96
85
- func (a * Manager ) HandleHTTP (w http.ResponseWriter , req * http.Request , h http.Handler ) {
97
+ func (m * Manager ) NewScope (rules ... Rule ) * Scope {
98
+ scope := NewScope (rules ... )
99
+ m .scopes = append (m .scopes , scope )
100
+ return scope
101
+ }
102
+
103
+ func (a * Manager ) HandleHTTP (w http.ResponseWriter , r * http.Request , h http.Handler ) {
86
104
next := h
87
105
88
- for _ , scope := range scopes {
106
+ for _ , scope := range a . scopes {
89
107
next = http .HandlerFunc (scope .HandleHTTP (next ))
90
108
}
91
109
92
110
next .ServeHTTP (w , r )
93
111
}
94
112
95
- func (a * Manager ) Listen (opts ServerOptions ) error {
113
+ type JSONRule struct {
114
+ ID string `json:"id"`
115
+ Name string `json:"name,omitempty"`
116
+ Description string `json:"description,omitempty"`
117
+ Config string `json:"config,omitempty"`
118
+ }
119
+
120
+ type JSONPlugin struct {
121
+ ID string `json:"id"`
122
+ Name string `json:"name,omitempty"`
123
+ Description string `json:"description,omitempty"`
124
+ Enabled bool `json:"enabled,omitempty"`
125
+ }
126
+
127
+ type JSONScope struct {
128
+ ID string `json:"id"`
129
+ Name string `json:"name,omitempty"`
130
+ Rules []JSONRule `json:"rules,omitempty"`
131
+ Plugins []JSONPlugin `json:"plugins,omitempty"`
132
+ }
133
+
134
+ func (a * Manager ) ServeAndListen (opts ServerOptions ) (* http.Server , error ) {
96
135
a .Server = NewServer (opts )
97
- return server .ListenAndServe ()
136
+
137
+ m := pat .New ()
138
+ a .Server .Handler = m
139
+
140
+ // Define route handlers
141
+ m .Get ("/" , http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
142
+ io .WriteString (w , "vinxi HTTP API manager " + Version )
143
+ }))
144
+
145
+ m .Get ("/scopes" , http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
146
+ buf := & bytes.Buffer {}
147
+ scopes := createScopes (a .scopes )
148
+
149
+ err := json .NewEncoder (buf ).Encode (scopes )
150
+ if err != nil {
151
+ w .WriteHeader (500 )
152
+ w .Write ([]byte (err .Error ()))
153
+ return
154
+ }
155
+
156
+ w .Write (buf .Bytes ())
157
+ }))
158
+
159
+ m .Get ("/scopes/:scope" , http .HandlerFunc (func (w http.ResponseWriter , req * http.Request ) {
160
+ id := req .URL .Query ().Get (":scope" )
161
+
162
+ // Find scope by ID
163
+ for _ , scope := range a .scopes {
164
+ if scope .ID == id {
165
+ data , err := encodeJSON (createScope (scope ))
166
+ if err != nil {
167
+ w .WriteHeader (500 )
168
+ w .Write ([]byte (err .Error ()))
169
+ return
170
+ }
171
+ w .Write (data )
172
+ return
173
+ }
174
+ }
175
+
176
+ w .WriteHeader (404 )
177
+ w .Write ([]byte ("not found" ))
178
+ }))
179
+
180
+ return a .Server , Listen (a .Server , opts )
181
+ }
182
+
183
+ func encodeJSON (data interface {}) ([]byte , error ) {
184
+ buf := & bytes.Buffer {}
185
+ err := json .NewEncoder (buf ).Encode (data )
186
+ return buf .Bytes (), err
187
+ }
188
+
189
+ func createScope (scope * Scope ) JSONScope {
190
+ return JSONScope {
191
+ ID : scope .ID ,
192
+ Name : scope .Name ,
193
+ Rules : createRules (scope ),
194
+ Plugins : createPlugins (scope ),
195
+ }
196
+ }
197
+
198
+ func createScopes (scopes []* Scope ) []JSONScope {
199
+ buf := make ([]JSONScope , len (scopes ))
200
+ for i , scope := range scopes {
201
+ buf [i ] = createScope (scope )
202
+ }
203
+ return buf
204
+ }
205
+
206
+ func createRules (scope * Scope ) []JSONRule {
207
+ rules := make ([]JSONRule , len (scope .rules ))
208
+ for i , rule := range scope .rules {
209
+ rules [i ] = JSONRule {ID : rule .ID (), Name : rule .Name (), Description : rule .Description (), Config : rule .JSONConfig ()}
210
+ }
211
+ return rules
212
+ }
213
+
214
+ func createPlugins (scope * Scope ) []JSONPlugin {
215
+ plugins := make ([]JSONPlugin , scope .plugins .Len ())
216
+ for i , plugin := range scope .plugins .pool {
217
+ plugins [i ] = JSONPlugin {ID : plugin .ID (), Name : plugin .Name (), Description : plugin .Description (), Enabled : plugin .IsEnabled ()}
218
+ }
219
+ return plugins
98
220
}
0 commit comments