diff options
author | Nimi Wariboko Jr <[email protected]> | 2015-05-03 13:33:08 -0700 |
---|---|---|
committer | Nimi Wariboko Jr <[email protected]> | 2015-05-03 13:33:08 -0700 |
commit | 264e5b7911a7741a01e14c8bc473df253f639309 (patch) | |
tree | f31ea3da0f66d335fcb14453673c41be0a878d60 | |
parent | a28d5585f5f01e489534d388818a0ffad487740d (diff) | |
download | caddy-264e5b7911a7741a01e14c8bc473df253f639309.tar.gz caddy-264e5b7911a7741a01e14c8bc473df253f639309.zip |
Use the provided Replacer tools in order to proxy string interpolation.
-rw-r--r-- | middleware/proxy/proxy.go | 78 |
1 files changed, 14 insertions, 64 deletions
diff --git a/middleware/proxy/proxy.go b/middleware/proxy/proxy.go index cc3b068da..083c27054 100644 --- a/middleware/proxy/proxy.go +++ b/middleware/proxy/proxy.go @@ -4,11 +4,8 @@ package proxy import ( "errors" "github.com/mholt/caddy/middleware" - "net" "net/http" "net/url" - "regexp" - "strings" "sync/atomic" "time" ) @@ -34,6 +31,7 @@ type UpstreamHostDownFunc func(*UpstreamHost) bool // An UpstreamHost represents a single proxy upstream type UpstreamHost struct { + // The hostname of this upstream host Name string ReverseProxy *ReverseProxy Conns int64 @@ -52,81 +50,27 @@ func (uh *UpstreamHost) Down() bool { return uh.CheckDown(uh) } -//https://github.com/mgutz/str -var tRe = regexp.MustCompile(`([\-\[\]()*\s])`) -var tRe2 = regexp.MustCompile(`\$`) -var openDelim = tRe2.ReplaceAllString(tRe.ReplaceAllString("{{", "\\$1"), "\\$") -var closDelim = tRe2.ReplaceAllString(tRe.ReplaceAllString("}}", "\\$1"), "\\$") -var templateDelim = regexp.MustCompile(openDelim + `(.+?)` + closDelim) - -type requestVars struct { - Host string - RemoteIp string - Scheme string - Upstream string - UpstreamHost string -} - -func templateWithDelimiters(s string, vars requestVars) string { - matches := templateDelim.FindAllStringSubmatch(s, -1) - for _, submatches := range matches { - match := submatches[0] - key := submatches[1] - found := true - repl := "" - switch key { - case "http_host": - repl = vars.Host - case "remote_addr": - repl = vars.RemoteIp - case "scheme": - repl = vars.Scheme - case "upstream": - repl = vars.Upstream - case "upstream_host": - repl = vars.UpstreamHost - default: - found = false - } - if found { - s = strings.Replace(s, match, repl, -1) - } - } - return s -} - // ServeHTTP satisfies the middleware.Handler interface. func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { for _, upstream := range p.Upstreams { if middleware.Path(r.URL.Path).Matches(upstream.From()) { - vars := requestVars{ - Host: r.Host, - Scheme: "http", - } - if clientIP, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { - vars.RemoteIp = clientIP - } - if fFor := r.Header.Get("X-Forwarded-For"); fFor != "" { - vars.RemoteIp = fFor - } - if r.TLS != nil { - vars.Scheme = "https" - } + var replacer middleware.Replacer + start := time.Now() + requestHost := r.Host + // Since Select() should give us "up" hosts, keep retrying // hosts until timeout (or until we get a nil host). - start := time.Now() for time.Now().Sub(start) < (60 * time.Second) { host := upstream.Select() if host == nil { return http.StatusBadGateway, errUnreachable } proxy := host.ReverseProxy - vars.Upstream = host.Name r.Host = host.Name if baseUrl, err := url.Parse(host.Name); err == nil { - vars.UpstreamHost = baseUrl.Host + r.Host = baseUrl.Host if proxy == nil { proxy = NewSingleHostReverseProxy(baseUrl) } @@ -136,12 +80,18 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { var extraHeaders http.Header if host.ExtraHeaders != nil { extraHeaders = make(http.Header) + if replacer == nil { + rHost := r.Host + r.Host = requestHost + replacer = middleware.NewReplacer(r, nil) + r.Host = rHost + } for header, values := range host.ExtraHeaders { for _, value := range values { extraHeaders.Add(header, - templateWithDelimiters(value, vars)) + replacer.Replace(value)) if header == "Host" { - r.Host = templateWithDelimiters(value, vars) + r.Host = replacer.Replace(value) } } } |