mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-26 02:09:47 +08:00
Merge pull request #984 from nemothekid/proxy/keepalive-directive
Proxy: Add keepalive directive to proxy to set MaxIdleConnsPerHost on transport
This commit is contained in:
commit
fffc1bed73
|
@ -108,7 +108,7 @@ func (p Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
|||
if nameURL, err := url.Parse(host.Name); err == nil {
|
||||
outreq.Host = nameURL.Host
|
||||
if proxy == nil {
|
||||
proxy = NewSingleHostReverseProxy(nameURL, host.WithoutPathPrefix)
|
||||
proxy = NewSingleHostReverseProxy(nameURL, host.WithoutPathPrefix, http.DefaultMaxIdleConnsPerHost)
|
||||
}
|
||||
|
||||
// use upstream credentials by default
|
||||
|
|
|
@ -725,11 +725,11 @@ func newFakeUpstream(name string, insecure bool) *fakeUpstream {
|
|||
from: "/",
|
||||
host: &UpstreamHost{
|
||||
Name: name,
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, ""),
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, "", http.DefaultMaxIdleConnsPerHost),
|
||||
},
|
||||
}
|
||||
if insecure {
|
||||
u.host.ReverseProxy.Transport = InsecureTransport
|
||||
u.host.ReverseProxy.UseInsecureTransport()
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
@ -753,7 +753,7 @@ func (u *fakeUpstream) Select(r *http.Request) *UpstreamHost {
|
|||
}
|
||||
u.host = &UpstreamHost{
|
||||
Name: u.name,
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, u.without),
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, u.without, http.DefaultMaxIdleConnsPerHost),
|
||||
}
|
||||
}
|
||||
return u.host
|
||||
|
@ -794,7 +794,7 @@ func (u *fakeWsUpstream) Select(r *http.Request) *UpstreamHost {
|
|||
uri, _ := url.Parse(u.name)
|
||||
return &UpstreamHost{
|
||||
Name: u.name,
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, u.without),
|
||||
ReverseProxy: NewSingleHostReverseProxy(uri, u.without, http.DefaultMaxIdleConnsPerHost),
|
||||
UpstreamHeaders: http.Header{
|
||||
"Connection": {"{>Connection}"},
|
||||
"Upgrade": {"{>Upgrade}"}},
|
||||
|
|
|
@ -83,7 +83,7 @@ func socketDial(hostName string) func(network, addr string) (conn net.Conn, err
|
|||
// the target request will be for /base/dir.
|
||||
// Without logic: target's path is "/", incoming is "/api/messages",
|
||||
// without is "/api", then the target request will be for /messages.
|
||||
func NewSingleHostReverseProxy(target *url.URL, without string) *ReverseProxy {
|
||||
func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int) *ReverseProxy {
|
||||
targetQuery := target.RawQuery
|
||||
director := func(req *http.Request) {
|
||||
if target.Scheme == "unix" {
|
||||
|
@ -122,10 +122,47 @@ func NewSingleHostReverseProxy(target *url.URL, without string) *ReverseProxy {
|
|||
rp.Transport = &http.Transport{
|
||||
Dial: socketDial(target.String()),
|
||||
}
|
||||
} else if keepalive != http.DefaultMaxIdleConnsPerHost {
|
||||
// if keepalive is equal to the default,
|
||||
// just use default transport, to avoid creating
|
||||
// a brand new transport
|
||||
rp.Transport = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
if keepalive == 0 {
|
||||
rp.Transport.(*http.Transport).DisableKeepAlives = true
|
||||
} else {
|
||||
rp.Transport.(*http.Transport).MaxIdleConnsPerHost = keepalive
|
||||
}
|
||||
}
|
||||
return rp
|
||||
}
|
||||
|
||||
// InsecureTransport is used to facilitate HTTPS proxying
|
||||
// when it is OK for upstream to be using a bad certificate,
|
||||
// since this transport skips verification.
|
||||
func (rp *ReverseProxy) UseInsecureTransport() {
|
||||
if rp.Transport == nil {
|
||||
rp.Transport = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
} else if transport, ok := rp.Transport.(*http.Transport); ok {
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
}
|
||||
|
||||
func copyHeader(dst, src http.Header) {
|
||||
for k, vv := range src {
|
||||
for _, v := range vv {
|
||||
|
@ -147,19 +184,6 @@ var hopHeaders = []string{
|
|||
"Upgrade",
|
||||
}
|
||||
|
||||
// InsecureTransport is used to facilitate HTTPS proxying
|
||||
// when it is OK for upstream to be using a bad certificate,
|
||||
// since this transport skips verification.
|
||||
var InsecureTransport http.RoundTripper = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
|
||||
type respUpdateFn func(resp *http.Response)
|
||||
|
||||
func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, outreq *http.Request, respUpdateFn respUpdateFn) error {
|
||||
|
|
|
@ -25,6 +25,7 @@ type staticUpstream struct {
|
|||
downstreamHeaders http.Header
|
||||
Hosts HostPool
|
||||
Policy Policy
|
||||
KeepAlive int
|
||||
insecureSkipVerify bool
|
||||
|
||||
FailTimeout time.Duration
|
||||
|
@ -54,6 +55,7 @@ func NewStaticUpstreams(c caddyfile.Dispenser) ([]Upstream, error) {
|
|||
FailTimeout: 10 * time.Second,
|
||||
MaxFails: 1,
|
||||
MaxConns: 0,
|
||||
KeepAlive: http.DefaultMaxIdleConnsPerHost,
|
||||
}
|
||||
|
||||
if !c.Args(&upstream.from) {
|
||||
|
@ -154,9 +156,9 @@ func (u *staticUpstream) NewHost(host string) (*UpstreamHost, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
uh.ReverseProxy = NewSingleHostReverseProxy(baseURL, uh.WithoutPathPrefix)
|
||||
uh.ReverseProxy = NewSingleHostReverseProxy(baseURL, uh.WithoutPathPrefix, u.KeepAlive)
|
||||
if u.insecureSkipVerify {
|
||||
uh.ReverseProxy.Transport = InsecureTransport
|
||||
uh.ReverseProxy.UseInsecureTransport()
|
||||
}
|
||||
|
||||
return uh, nil
|
||||
|
@ -312,6 +314,18 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream) error {
|
|||
u.IgnoredSubPaths = ignoredPaths
|
||||
case "insecure_skip_verify":
|
||||
u.insecureSkipVerify = true
|
||||
case "keepalive":
|
||||
if !c.NextArg() {
|
||||
return c.ArgErr()
|
||||
}
|
||||
n, err := strconv.Atoi(c.Val())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if n < 0 {
|
||||
return c.ArgErr()
|
||||
}
|
||||
u.KeepAlive = n
|
||||
default:
|
||||
return c.Errf("unknown property '%s'", c.Val())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user