diff --git a/build-and-push-images.sh b/build-and-push-images.sh index 7d07b17..1a07e83 100755 --- a/build-and-push-images.sh +++ b/build-and-push-images.sh @@ -3,6 +3,6 @@ ## Pushes to PKB private repository, change the registry if you want to push it elsewhere ## Increment this number when you push a new image -VERSION=6 +VERSION=7 docker build . -t "europe-docker.pkg.dev/infra-240614/eu.gcr.io/regproxy2:$VERSION" docker push "europe-docker.pkg.dev/infra-240614/eu.gcr.io/regproxy2:$VERSION" diff --git a/go.mod b/go.mod index f4aa50b..cba70f9 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module regproxy2 go 1.22.5 require ( + github.com/google/uuid v1.6.0 go.mercari.io/go-dnscache v0.0.0-20210517095825-88b046eb94f2 go.uber.org/zap v1.19.1 golang.org/x/sync v0.7.0 diff --git a/go.sum b/go.sum index e2502c2..e991893 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,20 @@ +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.mercari.io/go-dnscache v0.0.0-20210517095825-88b046eb94f2 h1:taxAJyuaSy+ImlJQDGBQcHz95SsJPhhHF3nIVt8oNAQ= @@ -15,6 +22,7 @@ go.mercari.io/go-dnscache v0.0.0-20210517095825-88b046eb94f2/go.mod h1:gwf+m/jHT go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= @@ -50,6 +58,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 4f03c50..d46d144 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "sync" "time" + "github.com/google/uuid" "go.mercari.io/go-dnscache" "go.uber.org/zap" ) @@ -160,36 +161,38 @@ func (p *RegProxy) proxy(resp http.ResponseWriter, req *http.Request) { // net/http/httputil.ReverseProxy implementation, it doesn't let us // forward to _multiple_ upstreams and choose a response based on header // so we can't use it here unfortunately + requestId := uuid.New() req2 := req.Clone(req.Context()) req2.RequestURI = "" // Isn't allowed to be set on client requests req2.Body = io.NopCloser(bytes.NewReader(b)) req2.URL.Host = callback.Host req2.URL.Scheme = callback.Scheme - log.Printf("Forwarding request %s to upstream %s at %s", req2.URL.Path, name, callback) + log.Printf("Forwarding request %s (ID %v) to upstream %s at %s", req2.URL.Path, requestId, name, callback) + requestStart := time.Now() resp2, err := p.client.Do(req2) + requestDuration := time.Now().Sub(requestStart) + if err != nil { - log.Printf("Error forwarding request %s to upstream %s at %s: %v", req2.URL.Path, name, callback, err) + log.Printf("Error forwarding request %s (ID %v) to upstream %s at %s: %v", req2.URL.Path, requestId, name, callback, err) ec <- err + } else if !isSuccess(resp2) { + log.Printf("Error forwarding request %s (ID %v) to upstream %s at %s: %v", req2.URL.Path, requestId, name, callback, resp2.StatusCode) + ec <- fmt.Errorf("unsuccessful status code for request %s (ID %v): %v", req2.URL.Path, requestId, resp2.StatusCode) } else { - log.Printf("Success forwarding request %s to upstream %s at %s: %v", req2.URL.Path, name, callback, resp2.StatusCode) + log.Printf("Success forwarding request %s (ID %v) to upstream %s at %s in %v: %v", req2.URL.Path, requestId, name, callback, requestDuration, resp2.StatusCode) rc <- resp2 } }(name, callback) } var latestSuccess *http.Response - var latestErr *http.Response dc := req.Context().Done() // Wait for _all_ the responses, it's interesting to know which ones succeeded and // which ones failed during a single call. for range upstreams { select { case latest := <-rc: - if isSuccess(latest) { - latestSuccess = latest - } else { - latestErr = latest - } + latestSuccess = latest case e = <-ec: // If our own client cancelled, we should stop waiting case _ = <-dc: @@ -202,13 +205,10 @@ func (p *RegProxy) proxy(resp http.ResponseWriter, req *http.Request) { errResp(resp, e) return } - // Prefer to return non-success responses - var rr = latestSuccess - if latestErr != nil { - rr = latestErr - } - resp.WriteHeader(rr.StatusCode) - _ = rr.Write(resp) + + // Otherwise write latest success + resp.WriteHeader(latestSuccess.StatusCode) + _ = latestSuccess.Write(resp) } type upstream struct { diff --git a/main_test.go b/main_test.go index 2d420f5..cdfc5cb 100644 --- a/main_test.go +++ b/main_test.go @@ -186,8 +186,8 @@ func TestOneFail(t *testing.T) { if err != nil { t.Fatal(err) } - if r.StatusCode != 404 { - t.Errorf("Expected 404, got %v", r.StatusCode) + if r.StatusCode != 500 { + t.Errorf("Expected 500, got %v", r.StatusCode) } /*rbs := string(rb) if rbs != testResponse {