}
type proxyRepo struct {
- url *url.URL
- path string
- redactedURL string
+ url *url.URL // The combined module proxy URL joined with the module path.
+ path string // The module path (unescaped).
+ redactedBase string // The base module proxy URL in [url.URL.Redacted] form.
listLatestOnce sync.Once
listLatest *RevInfo
}
func newProxyRepo(baseURL, path string) (Repo, error) {
+ // Parse the base proxy URL.
base, err := url.Parse(baseURL)
if err != nil {
return nil, err
}
+ redactedBase := base.Redacted()
switch base.Scheme {
case "http", "https":
// ok
case "file":
if *base != (url.URL{Scheme: base.Scheme, Path: base.Path, RawPath: base.RawPath}) {
- return nil, fmt.Errorf("invalid file:// proxy URL with non-path elements: %s", base.Redacted())
+ return nil, fmt.Errorf("invalid file:// proxy URL with non-path elements: %s", redactedBase)
}
case "":
- return nil, fmt.Errorf("invalid proxy URL missing scheme: %s", base.Redacted())
+ return nil, fmt.Errorf("invalid proxy URL missing scheme: %s", redactedBase)
default:
- return nil, fmt.Errorf("invalid proxy URL scheme (must be https, http, file): %s", base.Redacted())
+ return nil, fmt.Errorf("invalid proxy URL scheme (must be https, http, file): %s", redactedBase)
}
+ // Append the module path to the URL.
+ url := base
enc, err := module.EscapePath(path)
if err != nil {
return nil, err
}
- redactedURL := base.Redacted()
- base.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc
- base.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc)
- return &proxyRepo{base, path, redactedURL, sync.Once{}, nil, nil}, nil
+ url.Path = strings.TrimSuffix(base.Path, "/") + "/" + enc
+ url.RawPath = strings.TrimSuffix(base.RawPath, "/") + "/" + pathEscape(enc)
+
+ return &proxyRepo{url, path, redactedBase, sync.Once{}, nil, nil}, nil
}
func (p *proxyRepo) ModulePath() string {
}
func (p *proxyRepo) getBytes(ctx context.Context, path string) ([]byte, error) {
- body, err := p.getBody(ctx, path)
+ body, redactedURL, err := p.getBody(ctx, path)
if err != nil {
return nil, err
}
b, err := io.ReadAll(body)
if err != nil {
- // net/http doesn't add context to Body errors, so add it here.
+ // net/http doesn't add context to Body read errors, so add it here.
// (See https://go.dev/issue/52727.)
- return b, &url.Error{Op: "read", URL: strings.TrimSuffix(p.redactedURL, "/") + "/" + path, Err: err}
+ return b, &url.Error{Op: "read", URL: redactedURL, Err: err}
}
return b, nil
}
-func (p *proxyRepo) getBody(ctx context.Context, path string) (r io.ReadCloser, err error) {
+func (p *proxyRepo) getBody(ctx context.Context, path string) (r io.ReadCloser, redactedURL string, err error) {
fullPath := pathpkg.Join(p.url.Path, path)
target := *p.url
resp, err := web.Get(web.DefaultSecurity, &target)
if err != nil {
- return nil, err
+ return nil, "", err
}
if err := resp.Err(); err != nil {
resp.Body.Close()
- return nil, err
+ return nil, "", err
}
- return resp.Body, nil
+ return resp.Body, resp.URL, nil
}
func (p *proxyRepo) Versions(ctx context.Context, prefix string) (*Versions, error) {
}
info := new(RevInfo)
if err := json.Unmarshal(data, info); err != nil {
- return nil, p.versionError(rev, fmt.Errorf("invalid response from proxy %q: %w", p.redactedURL, err))
+ return nil, p.versionError(rev, fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
}
if info.Version != rev && rev == module.CanonicalVersion(rev) && module.Check(p.path, rev) == nil {
// If we request a correct, appropriate version for the module path, the
}
info := new(RevInfo)
if err := json.Unmarshal(data, info); err != nil {
- return nil, p.versionError("", fmt.Errorf("invalid response from proxy %q: %w", p.redactedURL, err))
+ return nil, p.versionError("", fmt.Errorf("invalid response from proxy %q: %w", p.redactedBase, err))
}
return info, nil
}
return p.versionError(version, err)
}
path := "@v/" + encVer + ".zip"
- body, err := p.getBody(ctx, path)
+ body, redactedURL, err := p.getBody(ctx, path)
if err != nil {
return p.versionError(version, err)
}
lr := &io.LimitedReader{R: body, N: codehost.MaxZipFile + 1}
if _, err := io.Copy(dst, lr); err != nil {
- // net/http doesn't add context to Body errors, so add it here.
+ // net/http doesn't add context to Body read errors, so add it here.
// (See https://go.dev/issue/52727.)
- err = &url.Error{Op: "read", URL: strings.TrimSuffix(p.redactedURL, "/") + "/" + path, Err: err}
+ err = &url.Error{Op: "read", URL: redactedURL, Err: err}
return p.versionError(version, err)
}
if lr.N <= 0 {