mirror of
https://github.com/therootcompany/golib.git
synced 2026-04-24 20:58:00 +00:00
refactor(geoip,check-ip): lift download/refresh out of geoip into cmd
geoip.Open now just opens files; download/refresh/polling logic lives at the cmd layer using dataset.Group with a combined httpcache.Cacher fetcher (or PollFiles when no GeoIP.conf is available). Removes geoip.OpenDatabases — the library is no longer concerned with refresh.
This commit is contained in:
parent
d8b6638d97
commit
9b92136f91
@ -37,7 +37,7 @@ type IPCheck struct {
|
|||||||
|
|
||||||
inbound *dataset.View[ipcohort.Cohort]
|
inbound *dataset.View[ipcohort.Cohort]
|
||||||
outbound *dataset.View[ipcohort.Cohort]
|
outbound *dataset.View[ipcohort.Cohort]
|
||||||
geo *geoip.Databases
|
geo *dataset.View[geoip.Databases]
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVersion(w *os.File) {
|
func printVersion(w *os.File) {
|
||||||
@ -103,16 +103,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
maxmind := filepath.Join(cfg.CacheDir, "maxmind")
|
maxmind := filepath.Join(cfg.CacheDir, "maxmind")
|
||||||
geo, err := geoip.OpenDatabases(
|
cityPath := filepath.Join(maxmind, geoip.CityEdition+".mmdb")
|
||||||
cfg.ConfPath,
|
asnPath := filepath.Join(maxmind, geoip.ASNEdition+".mmdb")
|
||||||
filepath.Join(maxmind, geoip.CityEdition+".mmdb"),
|
geoGroup := dataset.NewGroup(geoFetcher(cfg.ConfPath, cityPath, asnPath))
|
||||||
filepath.Join(maxmind, geoip.ASNEdition+".mmdb"),
|
cfg.geo = dataset.Add(geoGroup, func() (*geoip.Databases, error) {
|
||||||
)
|
return geoip.Open(cityPath, asnPath)
|
||||||
if err != nil {
|
})
|
||||||
|
if err := geoGroup.Load(context.Background()); err != nil {
|
||||||
log.Fatalf("geoip: %v", err)
|
log.Fatalf("geoip: %v", err)
|
||||||
}
|
}
|
||||||
defer func() { _ = geo.Close() }()
|
defer func() { _ = cfg.geo.Value().Close() }()
|
||||||
cfg.geo = geo
|
|
||||||
|
|
||||||
if cfg.Bind == "" {
|
if cfg.Bind == "" {
|
||||||
return
|
return
|
||||||
@ -121,9 +121,48 @@ func main() {
|
|||||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||||
defer stop()
|
defer stop()
|
||||||
go group.Tick(ctx, refreshInterval, func(err error) {
|
go group.Tick(ctx, refreshInterval, func(err error) {
|
||||||
log.Printf("refresh: %v", err)
|
log.Printf("blocklists refresh: %v", err)
|
||||||
|
})
|
||||||
|
go geoGroup.Tick(ctx, refreshInterval, func(err error) {
|
||||||
|
log.Printf("geoip refresh: %v", err)
|
||||||
})
|
})
|
||||||
if err := cfg.serve(ctx); err != nil {
|
if err := cfg.serve(ctx); err != nil {
|
||||||
log.Fatalf("serve: %v", err)
|
log.Fatalf("serve: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// geoFetcher returns a Fetcher for the GeoLite2 City + ASN .mmdb files.
|
||||||
|
// With a GeoIP.conf (explicit path or auto-discovered) both files are
|
||||||
|
// downloaded via httpcache conditional GETs; otherwise the files are
|
||||||
|
// expected to exist on disk and are polled for out-of-band changes.
|
||||||
|
func geoFetcher(confPath, cityPath, asnPath string) dataset.Fetcher {
|
||||||
|
if confPath == "" {
|
||||||
|
for _, p := range geoip.DefaultConfPaths() {
|
||||||
|
if _, err := os.Stat(p); err == nil {
|
||||||
|
confPath = p
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if confPath == "" {
|
||||||
|
return dataset.PollFiles(cityPath, asnPath)
|
||||||
|
}
|
||||||
|
conf, err := geoip.ParseConf(confPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("geoip-conf: %v", err)
|
||||||
|
}
|
||||||
|
dl := geoip.New(conf.AccountID, conf.LicenseKey)
|
||||||
|
city := dl.NewCacher(geoip.CityEdition, cityPath)
|
||||||
|
asn := dl.NewCacher(geoip.ASNEdition, asnPath)
|
||||||
|
return dataset.FetcherFunc(func() (bool, error) {
|
||||||
|
cityUpdated, err := city.Fetch()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("fetch %s: %w", geoip.CityEdition, err)
|
||||||
|
}
|
||||||
|
asnUpdated, err := asn.Fetch()
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("fetch %s: %w", geoip.ASNEdition, err)
|
||||||
|
}
|
||||||
|
return cityUpdated || asnUpdated, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ func (c *IPCheck) handle(w http.ResponseWriter, r *http.Request) {
|
|||||||
Blocked: in || out,
|
Blocked: in || out,
|
||||||
BlockedInbound: in,
|
BlockedInbound: in,
|
||||||
BlockedOutbound: out,
|
BlockedOutbound: out,
|
||||||
Geo: c.geo.Lookup(ip),
|
Geo: c.geo.Value().Lookup(ip),
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.URL.Query().Get("format") == "json" ||
|
if r.URL.Query().Get("format") == "json" ||
|
||||||
|
|||||||
@ -4,8 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/oschwald/geoip2-golang"
|
"github.com/oschwald/geoip2-golang"
|
||||||
)
|
)
|
||||||
@ -16,41 +14,6 @@ type Databases struct {
|
|||||||
ASN *geoip2.Reader
|
ASN *geoip2.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenDatabases resolves configuration, downloads stale .mmdb files (when a
|
|
||||||
// GeoIP.conf with credentials is available), and opens the readers.
|
|
||||||
//
|
|
||||||
// - confPath="" → auto-discover from DefaultConfPaths
|
|
||||||
// - conf found → auto-download to cityPath/asnPath
|
|
||||||
// - no conf → cityPath and asnPath must point to existing .mmdb files
|
|
||||||
func OpenDatabases(confPath, cityPath, asnPath string) (*Databases, error) {
|
|
||||||
if confPath == "" {
|
|
||||||
for _, p := range DefaultConfPaths() {
|
|
||||||
if _, err := os.Stat(p); err == nil {
|
|
||||||
confPath = p
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if confPath != "" {
|
|
||||||
cfg, err := ParseConf(confPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("geoip-conf: %w", err)
|
|
||||||
}
|
|
||||||
if err := os.MkdirAll(filepath.Dir(cityPath), 0o755); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
dl := New(cfg.AccountID, cfg.LicenseKey)
|
|
||||||
if _, err := dl.NewCacher(CityEdition, cityPath).Fetch(); err != nil {
|
|
||||||
return nil, fmt.Errorf("fetch %s: %w", CityEdition, err)
|
|
||||||
}
|
|
||||||
if _, err := dl.NewCacher(ASNEdition, asnPath).Fetch(); err != nil {
|
|
||||||
return nil, fmt.Errorf("fetch %s: %w", ASNEdition, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Open(cityPath, asnPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open opens city and ASN .mmdb files from the given paths.
|
// Open opens city and ASN .mmdb files from the given paths.
|
||||||
func Open(cityPath, asnPath string) (*Databases, error) {
|
func Open(cityPath, asnPath string) (*Databases, error) {
|
||||||
city, err := geoip2.Open(cityPath)
|
city, err := geoip2.Open(cityPath)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user