// constructBlock recursively processes tokens into a // JSON-encodable structure. To be used in a directive's // block. Goes to end of block. func constructBlock(d *parse.Dispenser) [][]interface{} { block := [][]interface{}{} for d.Next() { if d.Val() == "}" { break } block = append(block, constructLine(d)) } return block }
// constructLine transforms tokens into a JSON-encodable structure; // but only one line at a time, to be used at the top-level of // a server block only (where the first token on each line is a // directive) - not to be used at any other nesting level. func constructLine(d parse.Dispenser) interface{} { var args []interface{} all := d.RemainingArgs() for _, arg := range all { args = append(args, arg) } d.Next() if d.Val() == "{" { args = append(args, constructBlock(d)) } return args }
// NewStaticUpstreams parses the configuration input and sets up // static upstreams for the proxy middleware. func NewStaticUpstreams(c parse.Dispenser) ([]Upstream, error) { var upstreams []Upstream for c.Next() { upstream := &staticUpstream{ from: "", upstreamHeaders: make(http.Header), downstreamHeaders: make(http.Header), Hosts: nil, Policy: &Random{}, FailTimeout: 10 * time.Second, MaxFails: 1, MaxConns: 0, } if !c.Args(&upstream.from) { return upstreams, c.ArgErr() } to := c.RemainingArgs() if len(to) == 0 { return upstreams, c.ArgErr() } for c.NextBlock() { if err := parseBlock(&c, upstream); err != nil { return upstreams, err } } upstream.Hosts = make([]*UpstreamHost, len(to)) for i, host := range to { uh, err := upstream.NewHost(host) if err != nil { return upstreams, err } upstream.Hosts[i] = uh } if upstream.HealthCheck.Path != "" { go upstream.HealthCheckWorker(nil) } upstreams = append(upstreams, upstream) } return upstreams, nil }
// constructBlock recursively processes tokens into a // JSON-encodable structure. func constructBlock(d parse.Dispenser) interface{} { block := make(map[string]interface{}) for d.Next() { if d.Val() == "}" { break } dir := d.Val() all := d.RemainingArgs() var args []interface{} for _, arg := range all { args = append(args, arg) } if d.Val() == "{" { args = append(args, constructBlock(d)) } block[dir] = args } return block }
// NewStaticUpstreams parses the configuration input and sets up // static upstreams for the proxy middleware. func NewStaticUpstreams(c parse.Dispenser) ([]Upstream, error) { var upstreams []Upstream for c.Next() { upstream := &staticUpstream{ from: "", proxyHeaders: make(http.Header), hiddenHeaders: make(http.Header), Hosts: nil, Policy: &Random{}, FailTimeout: 10 * time.Second, MaxFails: 1, } if !c.Args(&upstream.from) { return upstreams, c.ArgErr() } to := c.RemainingArgs() if len(to) == 0 { return upstreams, c.ArgErr() } for c.NextBlock() { if err := parseBlock(&c, upstream); err != nil { return upstreams, err } } upstream.Hosts = make([]*UpstreamHost, len(to)) for i, host := range to { if !strings.HasPrefix(host, "http") && !strings.HasPrefix(host, "unix:") { host = "http://" + host } uh := &UpstreamHost{ Name: host, Conns: 0, Fails: 0, FailTimeout: upstream.FailTimeout, Unhealthy: false, ExtraHeaders: upstream.proxyHeaders, HiddenHeaders: upstream.hiddenHeaders, CheckDown: func(upstream *staticUpstream) UpstreamHostDownFunc { return func(uh *UpstreamHost) bool { if uh.Unhealthy { return true } if uh.Fails >= upstream.MaxFails && upstream.MaxFails != 0 { return true } return false } }(upstream), WithoutPathPrefix: upstream.WithoutPathPrefix, } if baseURL, err := url.Parse(uh.Name); err == nil { uh.ReverseProxy = NewSingleHostReverseProxy(baseURL, uh.WithoutPathPrefix) if upstream.insecureSkipVerify { uh.ReverseProxy.Transport = InsecureTransport } } else { return upstreams, err } upstream.Hosts[i] = uh } if upstream.HealthCheck.Path != "" { go upstream.HealthCheckWorker(nil) } upstreams = append(upstreams, upstream) } return upstreams, nil }