gofiber/fiber · error
proxy: parse upstream %q: %w
Error message
proxy: parse upstream %q: %w
What it means
Returned by parseUpstream when url.Parse fails on the raw upstream string. Bare hosts without a scheme are first prefixed with http://, so this fires only when even that constructed URL is syntactically invalid.
Source
Thrown at middleware/proxy/security.go:297
}
}
}
}
// parseUpstream returns the parsed url.URL for raw. Hosts without an
// explicit scheme default to http:// to match the historical Balancer
// behavior where bare "host:port" entries were accepted.
func parseUpstream(raw string) (*url.URL, error) {
raw = utils.TrimSpace(raw)
if raw == "" {
return nil, ErrUpstreamHostInvalid
}
if !strings.Contains(raw, "://") {
raw = "http://" + raw
}
u, err := url.Parse(raw)
if err != nil {
return nil, fmt.Errorf("proxy: parse upstream %q: %w", raw, err)
}
return u, nil
}
// validateUpstream parses raw, enforces the scheme allowlist, and unless
// the policy permits private addresses, resolves the hostname and
// rejects responses that include any blocked address. Rejecting on a
// single blocked answer mitigates DNS rebinding attempts in which the
// resolver returns a mix of public and private IPs.
func validateUpstream(raw string, policy SecurityPolicy) (*url.URL, error) {
u, err := parseUpstreamScheme(raw, policy)
if err != nil {
return nil, err
}
if policy.AllowPrivateIPs {
return u, nil
}
if err := validateHostForSSRF(u.Hostname()); err != nil {View on GitHub (pinned to 9a4c7e57fe)
Solutions
- Validate and sanitize the upstream string with net/url.Parse before configuring the proxy.
- Trim whitespace and reject strings with control characters.
- Construct upstream URLs from trusted components (scheme + host + port) rather than concatenating raw input.
Example fix
// before: passing raw config straight through
proxy.Do(ctx, cfg.UpstreamURL) // may be malformed
// after: pre-validate
u, err := url.Parse(strings.TrimSpace(cfg.UpstreamURL))
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, "bad upstream")
}
proxy.Do(ctx, u.String()) Defensive patterns
Strategy: validation
Validate before calling
// Validate the upstream URL parses before handing it to the proxy.
func validUpstream(raw string) (string, error) {
raw = strings.TrimSpace(raw)
if !strings.Contains(raw, "://") {
raw = "http://" + raw
}
u, err := url.Parse(raw)
if err != nil {
return "", err
}
return u.String(), nil
} Try / catch
if _, err := url.Parse(upstream); err != nil {
return fiber.NewError(fiber.StatusBadRequest,
"upstream URL is malformed")
}
return proxy.Do(c, upstream) Prevention
- Always url.Parse upstream strings sourced from config or users.
- Reject strings containing control bytes or whitespace.
- Construct upstreams from trusted scheme+host+port components.
When it happens
Trigger: Passing a malformed upstream to proxy.Do/Forward/Balancer, e.g. a string with illegal control characters, an invalid percent-encoding, or a scheme/authority that url.Parse rejects.
Common situations: User-controlled or config-supplied upstream URL with stray characters; unescaped spaces/control bytes; a typo like 'http//host'; copy-paste of a URL with backslashes or raw unicode.
Related errors
- proxy: nil client override passed to Do/Forward
- proxy: upstream scheme is not allowed
- proxy: upstream host is empty or invalid
- ErrUpstreamHostBlocked
- remote address cannot be empty
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/47335b7579cfd67b.json.
Report an issue: GitHub.