From f9f0c0024e24821eb1550eae9cd5de531f819e2d Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Tue, 6 Dec 2022 15:32:25 +0100 Subject: [PATCH] Fix Go 1.19 compatibility for unix socket reverse proxy URLs Since Go 1.19 the net/url URL.Parse function is changed when there is no host authority. This change broke the unix socket URL handling in the reverse proxy code. This change adds auto detection for the behavior and thus supports both old and new Go versions without having to add build constraints. Related: https://github.com/golang/go/issues/46059 --- caddyhttp/proxy/reverseproxy.go | 4 ++-- caddyhttp/proxy/unix.go | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 caddyhttp/proxy/unix.go diff --git a/caddyhttp/proxy/reverseproxy.go b/caddyhttp/proxy/reverseproxy.go index 28c9bcd5e66..b04a03842cd 100644 --- a/caddyhttp/proxy/reverseproxy.go +++ b/caddyhttp/proxy/reverseproxy.go @@ -113,7 +113,7 @@ type ReverseProxy struct { // "unix:///var/run/www.socket", hence the ambiguous trimming. func socketDial(hostName string, timeout time.Duration) func(network, addr string) (conn net.Conn, err error) { return func(network, addr string) (conn net.Conn, err error) { - return net.DialTimeout("unix", hostName[len("unix://"):], timeout) + return net.DialTimeout("unix", hostName[unixProtocolPrefixLength:], timeout) } } @@ -217,7 +217,7 @@ func NewSingleHostReverseProxy(target *url.URL, without string, keepalive int, t // to /var/run/www.socket/test, rendering paths useless. if target.Scheme == "unix" { // See comment on socketDial for the trim - socketPrefix := target.String()[len("unix://"):] + socketPrefix := target.String()[unixProtocolPrefixLength:] req.URL.Path = strings.TrimPrefix(req.URL.Path, socketPrefix) if req.URL.Opaque != "" { req.URL.Opaque = strings.TrimPrefix(req.URL.Opaque, socketPrefix) diff --git a/caddyhttp/proxy/unix.go b/caddyhttp/proxy/unix.go new file mode 100644 index 00000000000..6dce74e4e5d --- /dev/null +++ b/caddyhttp/proxy/unix.go @@ -0,0 +1,21 @@ +package proxy + +import ( + "net/url" + "strings" +) + +// unixProtocolPrefixLength defines the length of the prefix of parsed URLs +// starting with unix: scheme. The actual value is different since Go 1.19 where +// the prefix no longer contains a // as unix: is not a registered scheme. +// See https://github.com/golang/go/commit/ab0f7611d739fe10d0265dbc6bdc17684423bfc8 +// for reference. +var unixProtocolPrefixLength = func() int { + u, _ := url.Parse("unix:/some/path") + + if strings.HasPrefix(u.String(), "unix://") { + // For Go < 1.19 url parse generates strings with an injected //. + return len("unix://") + } + return len("unix:") +}()