fix(check-ip): continue without geoip data

This commit is contained in:
AJ ONeal 2026-09-15 12:00:25 -06:00
parent b02c784df7
commit aa747348ae
No known key found for this signature in database
2 changed files with 29 additions and 15 deletions

View File

@ -36,13 +36,13 @@ var webFS embed.FS
// Replaced by goreleaser / ldflags at build time.
var (
name = "check-ip"
version = "0.0.0-dev"
commit = "0000000"
date = "0001-01-01"
licenseYear = "2026"
name = "check-ip"
version = "0.0.0-dev"
commit = "0000000"
date = "0001-01-01"
licenseYear = "2026"
licenseOwner = "AJ ONeal"
licenseType = "MPL-2.0"
licenseType = "MPL-2.0"
)
// versionFromGit returns a tag scoped to this subdirectory, falling back to a short commit hash.
@ -316,10 +316,15 @@ func main() {
tGeo := time.Now()
if err := geoSet.Load(context.Background()); err != nil {
fmt.Fprintln(os.Stderr)
log.Fatalf("geoip: %v", err)
log.Printf("geoip unavailable: %v", err)
} else {
fmt.Fprintf(os.Stderr, "%s\n", time.Since(tGeo).Round(time.Millisecond))
}
fmt.Fprintf(os.Stderr, "%s\n", time.Since(tGeo).Round(time.Millisecond))
defer func() { _ = cfg.geo.Value().Close() }()
defer func() {
if databases := cfg.geo.Value(); databases != nil {
_ = databases.Close()
}
}()
// Whitelist: combined IPs + CIDRs in one file, polled for mtime changes.
// A match here overrides any block decision from the blocklists.

View File

@ -34,7 +34,10 @@ type Result struct {
// lookup builds a Result for ip against the currently loaded blocklists
// and GeoIP databases.
func (c *IPCheck) lookup(ip string) Result {
res := Result{IP: ip, Geo: c.geo.Value().Lookup(ip)}
res := Result{IP: ip}
if databases := c.geo.Value(); databases != nil {
res.Geo = databases.Lookup(ip)
}
addr, err := netip.ParseAddr(ip)
if err != nil {
res.Blocked = true
@ -54,12 +57,18 @@ func (c *IPCheck) lookup(ip string) Result {
// lookupRaw returns the raw geoip.Info for an IP.
func (c *IPCheck) lookupRaw(ip string) geoip.Info {
return c.geo.Value().Lookup(ip)
if databases := c.geo.Value(); databases != nil {
return databases.Lookup(ip)
}
return geoip.Info{}
}
// lookupRawCity returns the raw *geoip2.City record for an IP.
func (c *IPCheck) lookupRawCity(ip string) *geoip2.City {
return c.geo.Value().LookupRaw(ip)
if databases := c.geo.Value(); databases != nil {
return databases.LookupRaw(ip)
}
return nil
}
// writePretty renders res as space-aligned plain text.
@ -172,8 +181,8 @@ type dsStatus struct {
}
// healthz reports per-dataset load state and an overall ready flag.
// Returns 200 when all required sets (inbound, outbound, geoip) are
// loaded, 503 while any are still empty.
// Returns 200 when the blocklist sets are loaded. GeoIP is optional and may
// be unavailable while blocklist checks continue to work.
func (c *IPCheck) healthz(w http.ResponseWriter, _ *http.Request) {
cohortStatus := func(v *dataset.View[ipcohort.Cohort]) dsStatus {
s := dsStatus{LoadedAt: v.LoadedAt()}
@ -195,7 +204,7 @@ func (c *IPCheck) healthz(w http.ResponseWriter, _ *http.Request) {
datasets["whitelist"] = cohortStatus(c.whitelist)
}
ready := datasets["inbound"].Loaded && datasets["outbound"].Loaded && datasets["geoip"].Loaded
ready := datasets["inbound"].Loaded && datasets["outbound"].Loaded
resp := struct {
Ready bool `json:"ready"`
Version string `json:"version"`