platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
76
selective-vpn-api/app/egress_identity_geo.go
Normal file
76
selective-vpn-api/app/egress_identity_geo.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
egressutilpkg "selective-vpn-api/app/egressutil"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (s *egressIdentityService) lookupGeo(ip string, force bool) (string, string, error) {
|
||||
ip = strings.TrimSpace(ip)
|
||||
if ip == "" {
|
||||
return "", "", fmt.Errorf("empty ip")
|
||||
}
|
||||
now := time.Now()
|
||||
|
||||
s.geoMu.Lock()
|
||||
if entry, ok := s.geoCache[ip]; ok && !entry.ExpiresAt.IsZero() && now.Before(entry.ExpiresAt) {
|
||||
code := egressutilpkg.NormalizeCountryCode(entry.CountryCode)
|
||||
name := strings.TrimSpace(entry.CountryName)
|
||||
errMsg := strings.TrimSpace(entry.LastError)
|
||||
s.geoMu.Unlock()
|
||||
if code != "" || name != "" {
|
||||
return code, name, nil
|
||||
}
|
||||
if errMsg != "" && !force {
|
||||
return "", "", fmt.Errorf("%s", errMsg)
|
||||
}
|
||||
if !force {
|
||||
return "", "", nil
|
||||
}
|
||||
// Force refresh bypasses negative geo cache to recover country flag quickly.
|
||||
}
|
||||
stale := s.geoCache[ip]
|
||||
s.geoMu.Unlock()
|
||||
|
||||
geoURLs := egressGeoEndpointsForIP(ip)
|
||||
errs := make([]string, 0, len(geoURLs))
|
||||
for _, rawURL := range geoURLs {
|
||||
body, err := egressutilpkg.HTTPGetBody(egressHTTPClient, rawURL, egressIdentityGeoTimeout, "selective-vpn-api/egress-identity", 8*1024)
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
continue
|
||||
}
|
||||
code, name, err := egressutilpkg.ParseGeoResponse(body)
|
||||
if err != nil {
|
||||
errs = append(errs, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
s.geoMu.Lock()
|
||||
s.geoCache[ip] = egressGeoCacheEntry{
|
||||
CountryCode: egressutilpkg.NormalizeCountryCode(code),
|
||||
CountryName: strings.TrimSpace(name),
|
||||
ExpiresAt: now.Add(egressIdentityGeoCacheTTL),
|
||||
}
|
||||
s.geoMu.Unlock()
|
||||
return egressutilpkg.NormalizeCountryCode(code), strings.TrimSpace(name), nil
|
||||
}
|
||||
|
||||
if strings.TrimSpace(stale.CountryCode) != "" || strings.TrimSpace(stale.CountryName) != "" {
|
||||
return egressutilpkg.NormalizeCountryCode(stale.CountryCode), strings.TrimSpace(stale.CountryName), nil
|
||||
}
|
||||
|
||||
msg := "geo lookup failed"
|
||||
if len(errs) > 0 {
|
||||
msg = strings.Join(errs, "; ")
|
||||
}
|
||||
s.geoMu.Lock()
|
||||
s.geoCache[ip] = egressGeoCacheEntry{
|
||||
LastError: msg,
|
||||
ExpiresAt: now.Add(egressIdentityGeoFailTTL),
|
||||
}
|
||||
s.geoMu.Unlock()
|
||||
return "", "", fmt.Errorf("%s", msg)
|
||||
}
|
||||
Reference in New Issue
Block a user