mirror of
https://github.com/caddyserver/caddy.git
synced 2025-04-19 10:49:17 +08:00
Merge branch 'master' into active-health-transport
This commit is contained in:
commit
2c8c0286be
79
admin.go
79
admin.go
@ -221,7 +221,8 @@ func (admin *AdminConfig) newAdminHandler(addr NetworkAddress, remote bool, _ Co
|
|||||||
if remote {
|
if remote {
|
||||||
muxWrap.remoteControl = admin.Remote
|
muxWrap.remoteControl = admin.Remote
|
||||||
} else {
|
} else {
|
||||||
muxWrap.enforceHost = !addr.isWildcardInterface()
|
// see comment in allowedOrigins() as to why we disable the host check for unix/fd networks
|
||||||
|
muxWrap.enforceHost = !addr.isWildcardInterface() && !addr.IsUnixNetwork() && !addr.IsFdNetwork()
|
||||||
muxWrap.allowedOrigins = admin.allowedOrigins(addr)
|
muxWrap.allowedOrigins = admin.allowedOrigins(addr)
|
||||||
muxWrap.enforceOrigin = admin.EnforceOrigin
|
muxWrap.enforceOrigin = admin.EnforceOrigin
|
||||||
}
|
}
|
||||||
@ -310,47 +311,43 @@ func (admin AdminConfig) allowedOrigins(addr NetworkAddress) []*url.URL {
|
|||||||
for _, o := range admin.Origins {
|
for _, o := range admin.Origins {
|
||||||
uniqueOrigins[o] = struct{}{}
|
uniqueOrigins[o] = struct{}{}
|
||||||
}
|
}
|
||||||
if admin.Origins == nil {
|
// RFC 2616, Section 14.26:
|
||||||
|
// "A client MUST include a Host header field in all HTTP/1.1 request
|
||||||
|
// messages. If the requested URI does not include an Internet host
|
||||||
|
// name for the service being requested, then the Host header field MUST
|
||||||
|
// be given with an empty value."
|
||||||
|
//
|
||||||
|
// UPDATE July 2023: Go broke this by patching a minor security bug in 1.20.6.
|
||||||
|
// Understandable, but frustrating. See:
|
||||||
|
// https://github.com/golang/go/issues/60374
|
||||||
|
// See also the discussion here:
|
||||||
|
// https://github.com/golang/go/issues/61431
|
||||||
|
//
|
||||||
|
// We can no longer conform to RFC 2616 Section 14.26 from either Go or curl
|
||||||
|
// in purity. (Curl allowed no host between 7.40 and 7.50, but now requires a
|
||||||
|
// bogus host; see https://superuser.com/a/925610.) If we disable Host/Origin
|
||||||
|
// security checks, the infosec community assures me that it is secure to do
|
||||||
|
// so, because:
|
||||||
|
//
|
||||||
|
// 1) Browsers do not allow access to unix sockets
|
||||||
|
// 2) DNS is irrelevant to unix sockets
|
||||||
|
//
|
||||||
|
// If either of those two statements ever fail to hold true, it is not the
|
||||||
|
// fault of Caddy.
|
||||||
|
//
|
||||||
|
// Thus, we do not fill out allowed origins and do not enforce Host
|
||||||
|
// requirements for unix sockets. Enforcing it leads to confusion and
|
||||||
|
// frustration, when UDS have their own permissions from the OS.
|
||||||
|
// Enforcing host requirements here is effectively security theater,
|
||||||
|
// and a false sense of security.
|
||||||
|
//
|
||||||
|
// See also the discussion in #6832.
|
||||||
|
if admin.Origins == nil && !addr.IsUnixNetwork() && !addr.IsFdNetwork() {
|
||||||
if addr.isLoopback() {
|
if addr.isLoopback() {
|
||||||
if addr.IsUnixNetwork() || addr.IsFdNetwork() {
|
uniqueOrigins[net.JoinHostPort("localhost", addr.port())] = struct{}{}
|
||||||
// RFC 2616, Section 14.26:
|
uniqueOrigins[net.JoinHostPort("::1", addr.port())] = struct{}{}
|
||||||
// "A client MUST include a Host header field in all HTTP/1.1 request
|
uniqueOrigins[net.JoinHostPort("127.0.0.1", addr.port())] = struct{}{}
|
||||||
// messages. If the requested URI does not include an Internet host
|
} else {
|
||||||
// name for the service being requested, then the Host header field MUST
|
|
||||||
// be given with an empty value."
|
|
||||||
//
|
|
||||||
// UPDATE July 2023: Go broke this by patching a minor security bug in 1.20.6.
|
|
||||||
// Understandable, but frustrating. See:
|
|
||||||
// https://github.com/golang/go/issues/60374
|
|
||||||
// See also the discussion here:
|
|
||||||
// https://github.com/golang/go/issues/61431
|
|
||||||
//
|
|
||||||
// We can no longer conform to RFC 2616 Section 14.26 from either Go or curl
|
|
||||||
// in purity. (Curl allowed no host between 7.40 and 7.50, but now requires a
|
|
||||||
// bogus host; see https://superuser.com/a/925610.) If we disable Host/Origin
|
|
||||||
// security checks, the infosec community assures me that it is secure to do
|
|
||||||
// so, because:
|
|
||||||
// 1) Browsers do not allow access to unix sockets
|
|
||||||
// 2) DNS is irrelevant to unix sockets
|
|
||||||
//
|
|
||||||
// I am not quite ready to trust either of those external factors, so instead
|
|
||||||
// of disabling Host/Origin checks, we now allow specific Host values when
|
|
||||||
// accessing the admin endpoint over unix sockets. I definitely don't trust
|
|
||||||
// DNS (e.g. I don't trust 'localhost' to always resolve to the local host),
|
|
||||||
// and IP shouldn't even be used, but if it is for some reason, I think we can
|
|
||||||
// at least be reasonably assured that 127.0.0.1 and ::1 route to the local
|
|
||||||
// machine, meaning that a hypothetical browser origin would have to be on the
|
|
||||||
// local machine as well.
|
|
||||||
uniqueOrigins[""] = struct{}{}
|
|
||||||
uniqueOrigins["127.0.0.1"] = struct{}{}
|
|
||||||
uniqueOrigins["::1"] = struct{}{}
|
|
||||||
} else {
|
|
||||||
uniqueOrigins[net.JoinHostPort("localhost", addr.port())] = struct{}{}
|
|
||||||
uniqueOrigins[net.JoinHostPort("::1", addr.port())] = struct{}{}
|
|
||||||
uniqueOrigins[net.JoinHostPort("127.0.0.1", addr.port())] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !addr.IsUnixNetwork() && !addr.IsFdNetwork() {
|
|
||||||
uniqueOrigins[addr.JoinHostPort(0)] = struct{}{}
|
uniqueOrigins[addr.JoinHostPort(0)] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,6 +531,7 @@ func TestAdminRouterProvisioning(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAllowedOriginsUnixSocket(t *testing.T) {
|
func TestAllowedOriginsUnixSocket(t *testing.T) {
|
||||||
|
// see comment in allowedOrigins() as to why we do not fill out allowed origins for UDS
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
addr NetworkAddress
|
addr NetworkAddress
|
||||||
@ -543,12 +544,8 @@ func TestAllowedOriginsUnixSocket(t *testing.T) {
|
|||||||
Network: "unix",
|
Network: "unix",
|
||||||
Host: "/tmp/caddy.sock",
|
Host: "/tmp/caddy.sock",
|
||||||
},
|
},
|
||||||
origins: nil, // default origins
|
origins: nil, // default origins
|
||||||
expectOrigins: []string{
|
expectOrigins: []string{},
|
||||||
"", // empty host as per RFC 2616
|
|
||||||
"127.0.0.1",
|
|
||||||
"::1",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unix socket with custom origins",
|
name: "unix socket with custom origins",
|
||||||
@ -578,7 +575,7 @@ func TestAllowedOriginsUnixSocket(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
admin := AdminConfig{
|
admin := AdminConfig{
|
||||||
Origins: test.origins,
|
Origins: test.origins,
|
||||||
@ -592,7 +589,7 @@ func TestAllowedOriginsUnixSocket(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(gotOrigins) != len(test.expectOrigins) {
|
if len(gotOrigins) != len(test.expectOrigins) {
|
||||||
t.Errorf("Expected %d origins but got %d", len(test.expectOrigins), len(gotOrigins))
|
t.Errorf("%d: Expected %d origins but got %d", i, len(test.expectOrigins), len(gotOrigins))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,7 +604,7 @@ func TestAllowedOriginsUnixSocket(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectMap, gotMap) {
|
if !reflect.DeepEqual(expectMap, gotMap) {
|
||||||
t.Errorf("Origins mismatch.\nExpected: %v\nGot: %v", test.expectOrigins, gotOrigins)
|
t.Errorf("%d: Origins mismatch.\nExpected: %v\nGot: %v", i, test.expectOrigins, gotOrigins)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
4
go.mod
4
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/Masterminds/sprig/v3 v3.3.0
|
github.com/Masterminds/sprig/v3 v3.3.0
|
||||||
github.com/alecthomas/chroma/v2 v2.15.0
|
github.com/alecthomas/chroma/v2 v2.15.0
|
||||||
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
|
github.com/aryann/difflib v0.0.0-20210328193216-ff5ff6dc229b
|
||||||
github.com/caddyserver/certmagic v0.22.3-0.20250407182622-b9399eadfbe7
|
github.com/caddyserver/certmagic v0.23.0
|
||||||
github.com/caddyserver/zerossl v0.1.3
|
github.com/caddyserver/zerossl v0.1.3
|
||||||
github.com/cloudflare/circl v1.6.0
|
github.com/cloudflare/circl v1.6.0
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
@ -17,7 +17,7 @@ require (
|
|||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/klauspost/compress v1.18.0
|
github.com/klauspost/compress v1.18.0
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10
|
github.com/klauspost/cpuid/v2 v2.2.10
|
||||||
github.com/mholt/acmez/v3 v3.1.1
|
github.com/mholt/acmez/v3 v3.1.2
|
||||||
github.com/prometheus/client_golang v1.19.1
|
github.com/prometheus/client_golang v1.19.1
|
||||||
github.com/quic-go/quic-go v0.50.1
|
github.com/quic-go/quic-go v0.50.1
|
||||||
github.com/smallstep/certificates v0.26.1
|
github.com/smallstep/certificates v0.26.1
|
||||||
|
8
go.sum
8
go.sum
@ -93,8 +93,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||||
github.com/caddyserver/certmagic v0.22.3-0.20250407182622-b9399eadfbe7 h1:dZCbkHTYh2ulXpmUK4ZrYWMCTa7x4/F3w52RGQfYoIY=
|
github.com/caddyserver/certmagic v0.23.0 h1:CfpZ/50jMfG4+1J/u2LV6piJq4HOfO6ppOnOf7DkFEU=
|
||||||
github.com/caddyserver/certmagic v0.22.3-0.20250407182622-b9399eadfbe7/go.mod h1:r8ZK7Y8zaUU3j5g+oTiluLtQX8fwWI6MamcRINlSsJY=
|
github.com/caddyserver/certmagic v0.23.0/go.mod h1:9mEZIWqqWoI+Gf+4Trh04MOVPD0tGSxtqsxg87hAIH4=
|
||||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
@ -347,8 +347,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
|
|||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
github.com/mholt/acmez/v3 v3.1.1 h1:Jh+9uKHkPxUJdxM16q5mOr+G2V0aqkuFtNA28ihCxhQ=
|
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
|
||||||
github.com/mholt/acmez/v3 v3.1.1/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
github.com/mholt/acmez/v3 v3.1.2/go.mod h1:L1wOU06KKvq7tswuMDwKdcHeKpFFgkppZy/y0DFxagQ=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||||
|
@ -210,7 +210,7 @@ func (na NetworkAddress) IsUnixNetwork() bool {
|
|||||||
return IsUnixNetwork(na.Network)
|
return IsUnixNetwork(na.Network)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUnixNetwork returns true if na.Network is
|
// IsFdNetwork returns true if na.Network is
|
||||||
// fd or fdgram.
|
// fd or fdgram.
|
||||||
func (na NetworkAddress) IsFdNetwork() bool {
|
func (na NetworkAddress) IsFdNetwork() bool {
|
||||||
return IsFdNetwork(na.Network)
|
return IsFdNetwork(na.Network)
|
||||||
@ -641,7 +641,7 @@ func RegisterNetwork(network string, getListener ListenerFunc) {
|
|||||||
if network == "tcp" || network == "tcp4" || network == "tcp6" ||
|
if network == "tcp" || network == "tcp4" || network == "tcp6" ||
|
||||||
network == "udp" || network == "udp4" || network == "udp6" ||
|
network == "udp" || network == "udp4" || network == "udp6" ||
|
||||||
network == "unix" || network == "unixpacket" || network == "unixgram" ||
|
network == "unix" || network == "unixpacket" || network == "unixgram" ||
|
||||||
strings.HasPrefix("ip:", network) || strings.HasPrefix("ip4:", network) || strings.HasPrefix("ip6:", network) ||
|
strings.HasPrefix(network, "ip:") || strings.HasPrefix(network, "ip4:") || strings.HasPrefix(network, "ip6:") ||
|
||||||
network == "fd" || network == "fdgram" {
|
network == "fd" || network == "fdgram" {
|
||||||
panic("network type " + network + " is reserved")
|
panic("network type " + network + " is reserved")
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,9 @@ func (h *Handler) doActiveHealthCheckForAllHosts() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
networkAddr, err := caddy.NewReplacer().ReplaceOrErr(upstream.Dial, true, true)
|
repl := caddy.NewReplacer()
|
||||||
|
|
||||||
|
networkAddr, err := repl.ReplaceOrErr(upstream.Dial, true, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "invalid use of placeholders in dial address for active health checks"); c != nil {
|
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "invalid use of placeholders in dial address for active health checks"); c != nil {
|
||||||
c.Write(
|
c.Write(
|
||||||
@ -361,14 +363,24 @@ func (h *Handler) doActiveHealthCheckForAllHosts() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
hostAddr := addr.JoinHostPort(0)
|
hostAddr := addr.JoinHostPort(0)
|
||||||
dialAddr := hostAddr
|
|
||||||
if addr.IsUnixNetwork() || addr.IsFdNetwork() {
|
if addr.IsUnixNetwork() || addr.IsFdNetwork() {
|
||||||
// this will be used as the Host portion of a http.Request URL, and
|
// this will be used as the Host portion of a http.Request URL, and
|
||||||
// paths to socket files would produce an error when creating URL,
|
// paths to socket files would produce an error when creating URL,
|
||||||
// so use a fake Host value instead; unix sockets are usually local
|
// so use a fake Host value instead; unix sockets are usually local
|
||||||
hostAddr = "localhost"
|
hostAddr = "localhost"
|
||||||
}
|
}
|
||||||
err = h.doActiveHealthCheck(DialInfo{Network: addr.Network, Address: dialAddr}, hostAddr, networkAddr, upstream)
|
|
||||||
|
// Fill in the dial info for the upstream
|
||||||
|
// If the upstream is set, use that instead
|
||||||
|
dialInfoUpstream := upstream
|
||||||
|
if h.HealthChecks.Active.Upstream != "" {
|
||||||
|
dialInfoUpstream = &Upstream{
|
||||||
|
Dial: h.HealthChecks.Active.Upstream,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialInfo, _ := dialInfoUpstream.fillDialInfo(repl)
|
||||||
|
|
||||||
|
err = h.doActiveHealthCheck(dialInfo, hostAddr, networkAddr, upstream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "active health check failed"); c != nil {
|
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "active health check failed"); c != nil {
|
||||||
c.Write(
|
c.Write(
|
||||||
|
@ -17,7 +17,6 @@ package reverseproxy
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -100,8 +99,7 @@ func (u *Upstream) Full() bool {
|
|||||||
|
|
||||||
// fillDialInfo returns a filled DialInfo for upstream u, using the request
|
// fillDialInfo returns a filled DialInfo for upstream u, using the request
|
||||||
// context. Note that the returned value is not a pointer.
|
// context. Note that the returned value is not a pointer.
|
||||||
func (u *Upstream) fillDialInfo(r *http.Request) (DialInfo, error) {
|
func (u *Upstream) fillDialInfo(repl *caddy.Replacer) (DialInfo, error) {
|
||||||
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
|
|
||||||
var addr caddy.NetworkAddress
|
var addr caddy.NetworkAddress
|
||||||
|
|
||||||
// use provided dial address
|
// use provided dial address
|
||||||
|
@ -532,7 +532,7 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
|
|||||||
// the dial address may vary per-request if placeholders are
|
// the dial address may vary per-request if placeholders are
|
||||||
// used, so perform those replacements here; the resulting
|
// used, so perform those replacements here; the resulting
|
||||||
// DialInfo struct should have valid network address syntax
|
// DialInfo struct should have valid network address syntax
|
||||||
dialInfo, err := upstream.fillDialInfo(r)
|
dialInfo, err := upstream.fillDialInfo(repl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, fmt.Errorf("making dial info: %v", err)
|
return true, fmt.Errorf("making dial info: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user