fix application bug
This commit is contained in:
5
vendor/github.com/mholt/caddy/caddyhttp/proxy/policy.go
generated
vendored
5
vendor/github.com/mholt/caddy/caddyhttp/proxy/policy.go
generated
vendored
@@ -16,6 +16,7 @@ package proxy
|
||||
|
||||
import (
|
||||
"hash/fnv"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -139,7 +140,9 @@ func hostByHashing(pool HostPool, s string) *UpstreamHost {
|
||||
// hash calculates a hash based on string s
|
||||
func hash(s string) uint32 {
|
||||
h := fnv.New32a()
|
||||
h.Write([]byte(s))
|
||||
if _, err := h.Write([]byte(s)); err != nil {
|
||||
log.Println("[ERROR] failed to write bytes: ", err)
|
||||
}
|
||||
return h.Sum32()
|
||||
}
|
||||
|
||||
|
||||
29
vendor/github.com/mholt/caddy/caddyhttp/proxy/proxy.go
generated
vendored
29
vendor/github.com/mholt/caddy/caddyhttp/proxy/proxy.go
generated
vendored
@@ -92,8 +92,10 @@ type UpstreamHost struct {
|
||||
// This is an int32 so that we can use atomic operations to do concurrent
|
||||
// reads & writes to this value. The default value of 0 indicates that it
|
||||
// is healthy and any non-zero value indicates unhealthy.
|
||||
Unhealthy int32
|
||||
HealthCheckResult atomic.Value
|
||||
Unhealthy int32
|
||||
HealthCheckResult atomic.Value
|
||||
UpstreamHeaderReplacements headerReplacements
|
||||
DownstreamHeaderReplacements headerReplacements
|
||||
}
|
||||
|
||||
// Down checks whether the upstream host is down or not.
|
||||
@@ -220,7 +222,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
// set headers for request going upstream
|
||||
if host.UpstreamHeaders != nil {
|
||||
// modify headers for request that will be sent to the upstream host
|
||||
mutateHeadersByRules(outreq.Header, host.UpstreamHeaders, replacer)
|
||||
mutateHeadersByRules(outreq.Header, host.UpstreamHeaders, replacer, host.UpstreamHeaderReplacements)
|
||||
if hostHeaders, ok := outreq.Header["Host"]; ok && len(hostHeaders) > 0 {
|
||||
outreq.Host = hostHeaders[len(hostHeaders)-1]
|
||||
}
|
||||
@@ -230,7 +232,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
// headers coming back downstream
|
||||
var downHeaderUpdateFn respUpdateFn
|
||||
if host.DownstreamHeaders != nil {
|
||||
downHeaderUpdateFn = createRespHeaderUpdateFn(host.DownstreamHeaders, replacer)
|
||||
downHeaderUpdateFn = createRespHeaderUpdateFn(host.DownstreamHeaders, replacer, host.DownstreamHeaderReplacements)
|
||||
}
|
||||
|
||||
// Before we retry the request we have to make sure
|
||||
@@ -376,13 +378,13 @@ func createUpstreamRequest(rw http.ResponseWriter, r *http.Request) (*http.Reque
|
||||
return outreq, cancel
|
||||
}
|
||||
|
||||
func createRespHeaderUpdateFn(rules http.Header, replacer httpserver.Replacer) respUpdateFn {
|
||||
func createRespHeaderUpdateFn(rules http.Header, replacer httpserver.Replacer, replacements headerReplacements) respUpdateFn {
|
||||
return func(resp *http.Response) {
|
||||
mutateHeadersByRules(resp.Header, rules, replacer)
|
||||
mutateHeadersByRules(resp.Header, rules, replacer, replacements)
|
||||
}
|
||||
}
|
||||
|
||||
func mutateHeadersByRules(headers, rules http.Header, repl httpserver.Replacer) {
|
||||
func mutateHeadersByRules(headers, rules http.Header, repl httpserver.Replacer, replacements headerReplacements) {
|
||||
for ruleField, ruleValues := range rules {
|
||||
if strings.HasPrefix(ruleField, "+") {
|
||||
for _, ruleValue := range ruleValues {
|
||||
@@ -400,6 +402,19 @@ func mutateHeadersByRules(headers, rules http.Header, repl httpserver.Replacer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ruleField, ruleValues := range replacements {
|
||||
for _, ruleValue := range ruleValues {
|
||||
// Replace variables in replacement string
|
||||
replacement := repl.Replace(ruleValue.to)
|
||||
original := headers.Get(ruleField)
|
||||
if len(replacement) > 0 && len(original) > 0 {
|
||||
// Replace matches in original string with replacement string
|
||||
replaced := ruleValue.regexp.ReplaceAllString(original, replacement)
|
||||
headers.Set(ruleField, replaced)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CustomStatusContextCancelled = 499
|
||||
|
||||
35
vendor/github.com/mholt/caddy/caddyhttp/proxy/reverseproxy.go
generated
vendored
35
vendor/github.com/mholt/caddy/caddyhttp/proxy/reverseproxy.go
generated
vendored
@@ -31,6 +31,7 @@ import (
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -69,7 +70,9 @@ func pooledIoCopy(dst io.Writer, src io.Reader) {
|
||||
// Due to that we extend buf's length to its capacity here and
|
||||
// ensure it's always non-zero.
|
||||
bufCap := cap(buf)
|
||||
io.CopyBuffer(dst, src, buf[0:bufCap:bufCap])
|
||||
if _, err := io.CopyBuffer(dst, src, buf[0:bufCap:bufCap]); err != nil {
|
||||
log.Println("[ERROR] failed to copy buffer: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
// onExitFlushLoop is a callback set by tests to detect the state of the
|
||||
@@ -132,12 +135,12 @@ func (rp *ReverseProxy) srvDialerFunc(locator string, timeout time.Duration) fun
|
||||
}
|
||||
|
||||
func singleJoiningSlash(a, b string) string {
|
||||
aslash := strings.HasSuffix(a, "/")
|
||||
bslash := strings.HasPrefix(b, "/")
|
||||
aSlash := strings.HasSuffix(a, "/")
|
||||
bSlash := strings.HasPrefix(b, "/")
|
||||
switch {
|
||||
case aslash && bslash:
|
||||
case aSlash && bSlash:
|
||||
return a + b[1:]
|
||||
case !aslash && !bslash && b != "":
|
||||
case !aSlash && !bSlash && b != "":
|
||||
return a + "/" + b
|
||||
}
|
||||
return a + b
|
||||
@@ -275,7 +278,9 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int, t
|
||||
transport.MaxIdleConnsPerHost = keepalive
|
||||
}
|
||||
if httpserver.HTTP2 {
|
||||
http2.ConfigureTransport(transport)
|
||||
if err := http2.ConfigureTransport(transport); err != nil {
|
||||
log.Println("[ERROR] failed to configure transport to use HTTP/2: ", err)
|
||||
}
|
||||
}
|
||||
rp.Transport = transport
|
||||
} else {
|
||||
@@ -284,7 +289,9 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int, t
|
||||
Dial: rp.dialer.Dial,
|
||||
}
|
||||
if httpserver.HTTP2 {
|
||||
http2.ConfigureTransport(transport)
|
||||
if err := http2.ConfigureTransport(transport); err != nil {
|
||||
log.Println("[ERROR] failed to configure transport to use HTTP/2: ", err)
|
||||
}
|
||||
}
|
||||
rp.Transport = transport
|
||||
}
|
||||
@@ -394,7 +401,9 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outreq.Write(backendConn)
|
||||
if err := outreq.Write(backendConn); err != nil {
|
||||
log.Println("[ERROR] failed to write: ", err)
|
||||
}
|
||||
}
|
||||
defer backendConn.Close()
|
||||
|
||||
@@ -416,7 +425,9 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
backendConn.Write(rbuf)
|
||||
if _, err := backendConn.Write(rbuf); err != nil {
|
||||
log.Println("[ERROR] failed to write data to connection: ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
@@ -434,7 +445,7 @@ func (rp *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request,
|
||||
bodyOpen := true
|
||||
closeBody := func() {
|
||||
if bodyOpen {
|
||||
res.Body.Close()
|
||||
_ = res.Body.Close()
|
||||
bodyOpen = false
|
||||
}
|
||||
}
|
||||
@@ -681,7 +692,7 @@ func getTransportDialTLS(t *http.Transport) func(network, addr string) (net.Conn
|
||||
errc <- err
|
||||
}()
|
||||
if err := <-errc; err != nil {
|
||||
plainConn.Close()
|
||||
_ = plainConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if !tlsClientConfig.InsecureSkipVerify {
|
||||
@@ -690,7 +701,7 @@ func getTransportDialTLS(t *http.Transport) func(network, addr string) (net.Conn
|
||||
hostname = stripPort(addr)
|
||||
}
|
||||
if err := tlsConn.VerifyHostname(hostname); err != nil {
|
||||
plainConn.Close()
|
||||
_ = plainConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
118
vendor/github.com/mholt/caddy/caddyhttp/proxy/upstream.go
generated
vendored
118
vendor/github.com/mholt/caddy/caddyhttp/proxy/upstream.go
generated
vendored
@@ -21,10 +21,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -65,18 +68,39 @@ type staticUpstream struct {
|
||||
Port string
|
||||
ContentString string
|
||||
}
|
||||
WithoutPathPrefix string
|
||||
IgnoredSubPaths []string
|
||||
insecureSkipVerify bool
|
||||
MaxFails int32
|
||||
resolver srvResolver
|
||||
CaCertPool *x509.CertPool
|
||||
WithoutPathPrefix string
|
||||
IgnoredSubPaths []string
|
||||
insecureSkipVerify bool
|
||||
MaxFails int32
|
||||
resolver srvResolver
|
||||
CaCertPool *x509.CertPool
|
||||
upstreamHeaderReplacements headerReplacements
|
||||
downstreamHeaderReplacements headerReplacements
|
||||
}
|
||||
|
||||
type srvResolver interface {
|
||||
LookupSRV(context.Context, string, string, string) (string, []*net.SRV, error)
|
||||
}
|
||||
|
||||
// headerReplacement stores a compiled regex matcher and a string replacer, for replacement rules
|
||||
type headerReplacement struct {
|
||||
regexp *regexp.Regexp
|
||||
to string
|
||||
}
|
||||
|
||||
// headerReplacements stores a mapping of canonical MIME header to headerReplacement
|
||||
// Implements a subset of http.Header functions, to allow convenient addition and deletion of rules
|
||||
type headerReplacements map[string][]headerReplacement
|
||||
|
||||
func (h headerReplacements) Add(key string, value headerReplacement) {
|
||||
key = textproto.CanonicalMIMEHeaderKey(key)
|
||||
h[key] = append(h[key], value)
|
||||
}
|
||||
|
||||
func (h headerReplacements) Del(key string) {
|
||||
delete(h, textproto.CanonicalMIMEHeaderKey(key))
|
||||
}
|
||||
|
||||
// NewStaticUpstreams parses the configuration input and sets up
|
||||
// static upstreams for the proxy middleware. The host string parameter,
|
||||
// if not empty, is used for setting the upstream Host header for the
|
||||
@@ -86,18 +110,20 @@ func NewStaticUpstreams(c caddyfile.Dispenser, host string) ([]Upstream, error)
|
||||
for c.Next() {
|
||||
|
||||
upstream := &staticUpstream{
|
||||
from: "",
|
||||
stop: make(chan struct{}),
|
||||
upstreamHeaders: make(http.Header),
|
||||
downstreamHeaders: make(http.Header),
|
||||
Hosts: nil,
|
||||
Policy: &Random{},
|
||||
MaxFails: 1,
|
||||
TryInterval: 250 * time.Millisecond,
|
||||
MaxConns: 0,
|
||||
KeepAlive: http.DefaultMaxIdleConnsPerHost,
|
||||
Timeout: 30 * time.Second,
|
||||
resolver: net.DefaultResolver,
|
||||
from: "",
|
||||
stop: make(chan struct{}),
|
||||
upstreamHeaders: make(http.Header),
|
||||
downstreamHeaders: make(http.Header),
|
||||
Hosts: nil,
|
||||
Policy: &Random{},
|
||||
MaxFails: 1,
|
||||
TryInterval: 250 * time.Millisecond,
|
||||
MaxConns: 0,
|
||||
KeepAlive: http.DefaultMaxIdleConnsPerHost,
|
||||
Timeout: 30 * time.Second,
|
||||
resolver: net.DefaultResolver,
|
||||
upstreamHeaderReplacements: make(headerReplacements),
|
||||
downstreamHeaderReplacements: make(headerReplacements),
|
||||
}
|
||||
|
||||
if !c.Args(&upstream.from) {
|
||||
@@ -220,9 +246,11 @@ func (u *staticUpstream) NewHost(host string) (*UpstreamHost, error) {
|
||||
return false
|
||||
}
|
||||
}(u),
|
||||
WithoutPathPrefix: u.WithoutPathPrefix,
|
||||
MaxConns: u.MaxConns,
|
||||
HealthCheckResult: atomic.Value{},
|
||||
WithoutPathPrefix: u.WithoutPathPrefix,
|
||||
MaxConns: u.MaxConns,
|
||||
HealthCheckResult: atomic.Value{},
|
||||
UpstreamHeaderReplacements: u.upstreamHeaderReplacements,
|
||||
DownstreamHeaderReplacements: u.downstreamHeaderReplacements,
|
||||
}
|
||||
|
||||
baseURL, err := url.Parse(uh.Name)
|
||||
@@ -302,6 +330,8 @@ func parseUpstream(u string) ([]string, error) {
|
||||
}
|
||||
|
||||
func parseBlock(c *caddyfile.Dispenser, u *staticUpstream, hasSrv bool) error {
|
||||
var isUpstream bool
|
||||
|
||||
switch c.Val() {
|
||||
case "policy":
|
||||
if !c.NextArg() {
|
||||
@@ -431,23 +461,37 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream, hasSrv bool) error {
|
||||
}
|
||||
u.HealthCheck.ContentString = c.Val()
|
||||
case "header_upstream":
|
||||
var header, value string
|
||||
if !c.Args(&header, &value) {
|
||||
// When removing a header, the value can be optional.
|
||||
if !strings.HasPrefix(header, "-") {
|
||||
return c.ArgErr()
|
||||
}
|
||||
}
|
||||
u.upstreamHeaders.Add(header, value)
|
||||
isUpstream = true
|
||||
fallthrough
|
||||
case "header_downstream":
|
||||
var header, value string
|
||||
if !c.Args(&header, &value) {
|
||||
// When removing a header, the value can be optional.
|
||||
if !strings.HasPrefix(header, "-") {
|
||||
var header, value, replaced string
|
||||
if c.Args(&header, &value, &replaced) {
|
||||
// Don't allow - or + in replacements
|
||||
if strings.HasPrefix(header, "-") || strings.HasPrefix(header, "+") {
|
||||
return c.ArgErr()
|
||||
}
|
||||
r, err := regexp.Compile(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isUpstream {
|
||||
u.upstreamHeaderReplacements.Add(header, headerReplacement{r, replaced})
|
||||
} else {
|
||||
u.downstreamHeaderReplacements.Add(header, headerReplacement{r, replaced})
|
||||
}
|
||||
} else {
|
||||
if len(value) == 0 {
|
||||
// When removing a header, the value can be optional.
|
||||
if !strings.HasPrefix(header, "-") {
|
||||
return c.ArgErr()
|
||||
}
|
||||
}
|
||||
if isUpstream {
|
||||
u.upstreamHeaders.Add(header, value)
|
||||
} else {
|
||||
u.downstreamHeaders.Add(header, value)
|
||||
}
|
||||
}
|
||||
u.downstreamHeaders.Add(header, value)
|
||||
case "transparent":
|
||||
// Note: X-Forwarded-For header is always being appended for proxy connections
|
||||
// See implementation of createUpstreamRequest in proxy.go
|
||||
@@ -589,8 +633,10 @@ func (u *staticUpstream) healthCheck() {
|
||||
return true
|
||||
}
|
||||
defer func() {
|
||||
io.Copy(ioutil.Discard, r.Body)
|
||||
r.Body.Close()
|
||||
if _, err := io.Copy(ioutil.Discard, r.Body); err != nil {
|
||||
log.Println("[ERROR] failed to copy: ", err)
|
||||
}
|
||||
_ = r.Body.Close()
|
||||
}()
|
||||
if r.StatusCode < 200 || r.StatusCode >= 400 {
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user