-
Notifications
You must be signed in to change notification settings - Fork 2
/
setup.go
136 lines (125 loc) · 2.64 KB
/
setup.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
package reverse_proxy
import (
"strconv"
"strings"
"time"
super "github.com/caibirdme/durian/server"
"github.com/mholt/caddy"
)
const (
pluginName = "proxy"
)
func init() {
caddy.RegisterPlugin(super.DirectiveProxy, caddy.Plugin{
ServerType: super.FastHTTPServerType,
Action: setup,
})
}
func setup(c *caddy.Controller) error {
cfg, err := parseProxy(c)
if nil != err {
return err
}
p, err := NewProxy(*cfg)
if nil != err {
return err
}
super.GetConfig(c).AddMiddleware(p.Handle)
return nil
}
type ProxyConfig struct {
location super.LocationMatcher
AddressList []string
UpstreamHeader []super.KVTuple
DownstreamHeader []super.KVTuple
Timeout time.Duration
MaxConn int
}
var (
defaultTimeout = 2 * time.Second
)
func parseProxy(c *caddy.Controller) (*ProxyConfig, error) {
c.Next()
cfg := ProxyConfig{Timeout: defaultTimeout}
firstLine := c.RemainingArgs()
location, err := super.NewLocationMatcher(firstLine)
if err != nil {
return nil, err
}
cfg.location = location
for c.NextBlock() {
kind := c.Val()
err := parseKind(kind, &cfg, c)
if nil != err {
return nil, err
}
}
return &cfg, nil
}
func parseKind(kind string, cfg *ProxyConfig, c *caddy.Controller) error {
switch strings.ToLower(kind) {
case "timeout":
if !c.NextArg() {
return c.Errf("[%s] timeout value isn't set", pluginName)
}
val := c.Val()
d, err := time.ParseDuration(val)
if nil != err {
return err
}
cfg.Timeout = d
case "header_upstream":
err := parseKVTuple(c, &cfg.UpstreamHeader)
if nil != err {
return err
}
case "header_downstream":
err := parseKVTuple(c, &cfg.DownstreamHeader)
if nil != err {
return err
}
case "upstream":
err := parseUpstream(c, cfg)
if nil != err {
return err
}
case "max_conn":
if !c.NextArg() {
return c.Err("need path value")
}
max_conn, err := strconv.Atoi(c.Val())
if err != nil {
return c.Err(err.Error())
}
cfg.MaxConn = max_conn
default:
return c.Errf("[%s] illegal directive %s", pluginName, kind)
}
return nil
}
func parseKVTuple(c *caddy.Controller, cfg *[]super.KVTuple) error {
var k, v string
if !c.Args(&k, &v) {
return c.ArgErr()
}
*cfg = append(*cfg, super.KVTuple{K: k, V: v})
return nil
}
// due to bug of Dispender, this is a workaround
func parseUpstream(c *caddy.Controller, cfg *ProxyConfig) error {
// {
if !c.Next() {
return c.ArgErr()
}
for c.Next() {
address := c.Val()
if address == "}" {
break
}
cfg.AddressList = append(cfg.AddressList, address)
}
if len(cfg.AddressList) == 0 {
return c.Errf("[%s] upstream should contain at least one address", pluginName)
}
return nil
}