router-for-me/CLIProxyAPI · warning

parse redirect base: %w

Error message

parse redirect base: %w

What it means

In pluginStoreRedirectURL the current (request) URL is parsed with url.Parse to serve as the base for resolving a relative Location. 'parse redirect base: %w' wraps that parse failure — the URL already being fetched could not be parsed as an absolute URL. It is a defensive check; normally the earlier request construction would have failed first.

Source

Thrown at internal/pluginstore/github.go:250

}

func pluginStoreRedirectStatus(status int) bool {
	switch status {
	case http.StatusMovedPermanently, http.StatusFound, http.StatusSeeOther, http.StatusTemporaryRedirect, http.StatusPermanentRedirect:
		return true
	default:
		return false
	}
}

func pluginStoreRedirectURL(resp *http.Response, requestURL string) (string, error) {
	location := strings.TrimSpace(resp.Header.Get("Location"))
	if location == "" {
		return "", fmt.Errorf("redirect missing Location header")
	}
	base, errBase := url.Parse(requestURL)
	if errBase != nil {
		return "", fmt.Errorf("parse redirect base: %w", errBase)
	}
	next, errNext := base.Parse(location)
	if errNext != nil {
		return "", fmt.Errorf("parse redirect location: %w", errNext)
	}
	if next.Scheme == "" || next.Host == "" {
		return "", fmt.Errorf("redirect location is not absolute")
	}
	return next.String(), nil
}

func readPluginStoreResponse(resp *http.Response, maxSize int64, authenticated bool) ([]byte, error) {
	defer func() {
		if errClose := resp.Body.Close(); errClose != nil {
			log.WithError(errClose).Debug("failed to close plugin store response body")
		}
	}()
	if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Validate/normalize the URL (url.Parse + check Scheme/Host) before handing it to the plugin store client.
  2. url.PathEscape any dynamic path components when building URLs.

Example fix

// before
u := fmt.Sprintf("https://host/plugins/%s", name) // name='my plugin' (space)

// after
u := fmt.Sprintf("https://host/plugins/%s", url.PathEscape(name))
Defensive patterns

Strategy: validation

Validate before calling

if _, err := url.Parse(rawURL); err != nil {
    return fmt.Errorf("unparseable plugin url %q: %w", rawURL, err)
}

Prevention

When it happens

Trigger: url.Parse(requestURL) failing on the in-flight URL — control characters or a truly malformed URL that somehow passed request creation (e.g. a non-standard HTTPDoer accepting the request). Note url.Parse is lenient; failures here require control characters or similar.

Common situations: Custom HTTPDoer implementations or tests injecting odd URLs; URLs containing raw CR/LF introduced dynamically between request creation and redirect handling.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/660dd10166d6b0c4. Report an issue: GitHub.