diff --git a/pkg/versiongetter/go.go b/pkg/versiongetter/go.go index 1ffbfa93a..09e1387a3 100644 --- a/pkg/versiongetter/go.go +++ b/pkg/versiongetter/go.go @@ -22,11 +22,11 @@ func NewGoGetter(gc GoProxyClient) *GoGetter { } type GoProxyClient interface { - List(ctx context.Context, path string) ([]string, error) + List(ctx context.Context, logE *logrus.Entry, path string) ([]string, error) } func (g *GoGetter) Get(ctx context.Context, logE *logrus.Entry, pkg *registry.PackageInfo, _ []*Filter) (string, error) { //nolint:cyclop - versions, err := g.gc.List(ctx, pkg.GoVersionPath) + versions, err := g.gc.List(ctx, logE, pkg.GoVersionPath) if err != nil { return "", fmt.Errorf("list versions: %w", err) } @@ -57,7 +57,7 @@ func (g *GoGetter) Get(ctx context.Context, logE *logrus.Entry, pkg *registry.Pa } func (g *GoGetter) List(ctx context.Context, logE *logrus.Entry, pkg *registry.PackageInfo, _ []*Filter, _ int) ([]*fuzzyfinder.Item, error) { - vs, err := g.gc.List(ctx, pkg.GoVersionPath) + vs, err := g.gc.List(ctx, logE, pkg.GoVersionPath) if err != nil { return nil, fmt.Errorf("list versions: %w", err) } diff --git a/pkg/versiongetter/goproxy/client.go b/pkg/versiongetter/goproxy/client.go index 8f5e11110..16147af4a 100644 --- a/pkg/versiongetter/goproxy/client.go +++ b/pkg/versiongetter/goproxy/client.go @@ -2,12 +2,20 @@ package goproxy import ( "context" + "encoding/json" "fmt" "io" "net/http" "strings" + + "github.com/sirupsen/logrus" + "github.com/suzuki-shunsuke/logrus-error/logerr" ) +type InfoPayload struct { + Version string +} + type Client struct { client *http.Client } @@ -18,8 +26,41 @@ func New(client *http.Client) *Client { } } -func (c *Client) List(ctx context.Context, path string) ([]string, error) { - req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://proxy.golang.org/%s/@v/list", path), nil) +func (c *Client) List(ctx context.Context, logE *logrus.Entry, path string) ([]string, error) { + listEndpoint := fmt.Sprintf("https://proxy.golang.org/%s/@v/list", path) + b, err := c.doHTTPRequest(ctx, listEndpoint) + if err != nil { + return nil, fmt.Errorf("retrieve package versions: %w", logerr.WithFields(err, logrus.Fields{ + "api_endpoint": listEndpoint, + })) + } + if s := strings.TrimSpace(string(b)); s != "" { + return strings.Split(s, "\n"), nil + } + + // Find the latest version (including pseudo-versions) if $module/@v/list is empty + latestEndpoint := fmt.Sprintf("https://proxy.golang.org/%s/@latest", path) + fields := logrus.Fields{ + "api_endpoint": latestEndpoint, + } + logE = logE.WithFields(fields) + b, err = c.doHTTPRequest(ctx, latestEndpoint) + if err != nil { + return nil, fmt.Errorf("retrieve the latest version: %w", logerr.WithFields(err, fields)) + } + if len(b) == 0 { + logE.Debug("the response body from go proxy is empty") + return nil, nil + } + payload := &InfoPayload{} + if err := json.Unmarshal(b, &payload); err != nil { + return nil, fmt.Errorf("decode the response body as JSON: %w", logerr.WithFields(err, fields)) + } + return []string{payload.Version}, nil +} + +func (c *Client) doHTTPRequest(ctx context.Context, uri string) ([]byte, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil) if err != nil { return nil, fmt.Errorf("create a http request: %w", err) } @@ -35,9 +76,5 @@ func (c *Client) List(ctx context.Context, path string) ([]string, error) { if err != nil { return nil, fmt.Errorf("read a response body: %w", err) } - s := strings.TrimSpace(string(b)) - if s == "" { - return nil, nil - } - return strings.Split(s, "\n"), nil + return b, nil }