tiup HTTP clients ignore NO_PROXY
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 466
- Forks
- 338
- Avg merge
- 3d 7h
- Merged PRs (30d)
- 8
Description
Bug Report
Please answer these questions before submitting your issue. Thanks!
- What did you do?
On a control machine behind an HTTP proxy (needed to reach the component mirror), with the cluster on an internal network excluded via NO_PROXY:
export HTTP_PROXY=http://internal-proxy:3128
export HTTPS_PROXY=http://internal-proxy:3128
export NO_PROXY=10.0.0.0/8,.internal.example.com,localhost,127.0.0.1
tiup cluster reload <cluster> -R tikv
- What did you expect to see?
NO_PROXY honored: internal hosts (PD, TiKV) reached directly; only the external component mirror goes through the proxy — the standard HTTP_PROXY/NO_PROXY contract.
- What did you see instead?
Every request is forced through HTTP_PROXY regardless of NO_PROXY, so the internal API calls fail. It surfaces in two stages of reload:
- PD API —
error requesting http://pd-1.internal.example.com:2379/pd/api/v1/config, ... code 403(the proxy rejects the internal request). - After fixing that, TiKV status scrape —
Error: failed to get leader count ...: metric tikv_raftstore_region_count{type="leader"} not found. tiup scrapeshttp://tikv-1.internal.example.com:20180/metricsto count leaders before restart; that request also goes through the proxy and returns the proxy's error page, so the metric can't be parsed.
(Conversely, without a proxy, InitConfig fails to fetch /timestamp.json from the mirror — there is no single configuration that works.)
- What version of TiUP are you using (
tiup --version)?
v1.16.5 (also reproduced on master).
Root cause
Two HTTP clients set tr.Proxy to a fixed http.ProxyURL (applied to every destination, ignoring NO_PROXY) instead of http.ProxyFromEnvironment:
pkg/utils/http_client.go→NewHTTPClient— used by the PD API client (pkg/cluster/api/pdapi.go).pkg/cluster/spec/tikv.go→makeTransport— used bygenLeaderCounterto scrape the TiKV status port.
httpProxy := os.Getenv("TIUP_INNER_HTTP_PROXY")
if len(httpProxy) == 0 {
httpProxy = os.Getenv("HTTP_PROXY")
}
if len(httpProxy) > 0 {
if proxyURL, err := url.Parse(httpProxy); err == nil {
tr.Proxy = http.ProxyURL(proxyURL) // ignores NO_PROXY
}
}
Proposed fix (backward compatible)
Resolve the proxy with golang.org/x/net/http/httpproxy so NO_PROXY is honored, keeping the TIUP_INNER_HTTP_PROXY override, in both clients:
import "golang.org/x/net/http/httpproxy"
proxyCfg := httpproxy.FromEnvironment() // HTTP(S)_PROXY + NO_PROXY
if inner := os.Getenv("TIUP_INNER_HTTP_PROXY"); len(inner) > 0 {
proxyCfg.HTTPProxy, proxyCfg.HTTPSProxy = inner, inner
}
proxyFunc := proxyCfg.ProxyFunc()
tr.Proxy = func(req *http.Request) (*url.URL, error) {
return proxyFunc(req.URL)
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read pkg/utils/http_client.go and pkg/cluster/spec/tikv.go, then trace NewHTTPClient, makeTransport, and their PD API and TiKV metric callers. Verify that internal requests honor NO_PROXY while the component mirror remains reachable through the proxy, and that TIUP_INNER_HTTP_PROXY continues to override the environment proxy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100