Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 51 additions & 11 deletions internal/api/handlers/management/api_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func (h *Handler) APICall(c *gin.Context) {
httpClient := &http.Client{
Timeout: defaultAPICallTimeout,
}
httpClient.Transport = h.apiCallTransport(auth)
httpClient.Transport = h.apiCallTransport(auth, parsedURL.Host)

resp, errDo := httpClient.Do(req)
if errDo != nil {
Expand Down Expand Up @@ -318,7 +318,7 @@ func (h *Handler) refreshGeminiOAuthAccessToken(ctx context.Context, auth *corea
ctxToken := ctx
httpClient := &http.Client{
Timeout: defaultAPICallTimeout,
Transport: h.apiCallTransport(auth),
Transport: h.apiCallTransport(auth, ""),
}
ctxToken = context.WithValue(ctxToken, oauth2.HTTPClient, httpClient)

Expand Down Expand Up @@ -377,7 +377,7 @@ func (h *Handler) refreshAntigravityOAuthAccessToken(ctx context.Context, auth *

httpClient := &http.Client{
Timeout: defaultAPICallTimeout,
Transport: h.apiCallTransport(auth),
Transport: h.apiCallTransport(auth, ""),
}
resp, errDo := httpClient.Do(req)
if errDo != nil {
Expand Down Expand Up @@ -631,16 +631,56 @@ func (h *Handler) authByIndex(authIndex string) *coreauth.Auth {
return nil
}

func (h *Handler) apiCallTransport(auth *coreauth.Auth) http.RoundTripper {
var proxyCandidates []string
if auth != nil {
if proxyStr := strings.TrimSpace(auth.ProxyURL); proxyStr != "" {
proxyCandidates = append(proxyCandidates, proxyStr)
// defaultNoProxyCIDRs are RFC 1918/4193 private ranges, loopback, and link-local.
// Requests to hosts within these ranges bypass the configured proxy in the
// management api-call handler, because proxies typically cannot reach LAN targets.
var defaultNoProxyCIDRs = []string{
"127.0.0.0/8",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"169.254.0.0/16",
"::1/128",
"fc00::/7",
"fe80::/10",
}

// isNoProxyHost returns true when targetHost should bypass the proxy.
func isNoProxyHost(targetHost string) bool {
host := targetHost
if h, _, err := net.SplitHostPort(host); err == nil {
host = h
}
ip := net.ParseIP(host)
if ip == nil {
return false
}
for _, cidr := range defaultNoProxyCIDRs {
_, network, err := net.ParseCIDR(cidr)
if err != nil {
continue
}
if network.Contains(ip) {
return true
}
}
if h != nil && h.cfg != nil {
if proxyStr := strings.TrimSpace(h.cfg.ProxyURL); proxyStr != "" {
proxyCandidates = append(proxyCandidates, proxyStr)
return false
}
Comment on lines +637 to +668
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation of isNoProxyHost parses the hardcoded CIDR strings on every function call. This is inefficient as it can be done once at application startup.

Additionally, if one of the hardcoded CIDRs is invalid, net.ParseCIDR will return an error which is silently ignored with continue. For hardcoded values, it's better to fail fast at startup if they are invalid.

I suggest pre-parsing the CIDRs into a slice of *net.IPNet during initialization. This improves performance and makes the logic more robust.

var defaultNoProxyCIDRs = []string{
	"127.0.0.0/8",
	"10.0.0.0/8",
	"172.16.0.0/12",
	"192.168.0.0/16",
	"169.254.0.0/16",
	"::1/128",
	"fc00::/7",
	"fe80::/10",
}

var parsedNoProxyCIDRs = func() []*net.IPNet {
	cidrs := make([]*net.IPNet, 0, len(defaultNoProxyCIDRs))
	for _, cidr := range defaultNoProxyCIDRs {
		_, network, err := net.ParseCIDR(cidr)
		if err != nil {
			// Panic on startup if hardcoded CIDRs are invalid.
			panic(fmt.Sprintf("invalid hardcoded CIDR in defaultNoProxyCIDRs: %q: %v", cidr, err))
		}
		cidrs = append(cidrs, network)
	}
	return cidrs
}()

// isNoProxyHost returns true when targetHost should bypass the proxy.
func isNoProxyHost(targetHost string) bool {
	if targetHost == "" {
		return false
	}
	host := targetHost
	if h, _, err := net.SplitHostPort(host); err == nil {
		host = h
	}
	ip := net.ParseIP(host)
	if ip == nil {
		return false
	}
	for _, network := range parsedNoProxyCIDRs {
		if network.Contains(ip) {
			return true
		}
	}
	return false
}


func (h *Handler) apiCallTransport(auth *coreauth.Auth, targetHost string) http.RoundTripper {
noProxy := isNoProxyHost(targetHost)

var proxyCandidates []string
if !noProxy {
if auth != nil {
if proxyStr := strings.TrimSpace(auth.ProxyURL); proxyStr != "" {
proxyCandidates = append(proxyCandidates, proxyStr)
}
}
if h != nil && h.cfg != nil {
if proxyStr := strings.TrimSpace(h.cfg.ProxyURL); proxyStr != "" {
proxyCandidates = append(proxyCandidates, proxyStr)
}
}
}

Expand Down