refactor(geoip): ParseConf takes a string, not a file path

The old ParseConf opened the file itself, which the name did not
convey. Now it parses the config text directly, matching
encoding/json.Unmarshal-style conventions: callers read the file (or
source the string however they like) and pass it in. Also introduce
errors.ErrMissingCredentials for the credential-missing case so callers
can branch on it.
This commit is contained in:
AJ ONeal 2026-04-20 16:53:17 -06:00
parent e329c0f86b
commit 4753888402
No known key found for this signature in database
4 changed files with 23 additions and 17 deletions

View File

@ -104,7 +104,11 @@ func main() {
} }
} }
if cfg.GeoIPConfPath != "" { if cfg.GeoIPConfPath != "" {
conf, err := geoip.ParseConf(cfg.GeoIPConfPath) data, err := os.ReadFile(cfg.GeoIPConfPath)
if err != nil {
log.Fatalf("geoip-conf: %v", err)
}
conf, err := geoip.ParseConf(string(data))
if err != nil { if err != nil {
log.Fatalf("geoip-conf: %v", err) log.Fatalf("geoip-conf: %v", err)
} }

View File

@ -17,7 +17,12 @@ func main() {
freshDays := flag.Int("fresh-days", 3, "skip download if file is younger than N days") freshDays := flag.Int("fresh-days", 3, "skip download if file is younger than N days")
flag.Parse() flag.Parse()
cfg, err := geoip.ParseConf(*configPath) data, err := os.ReadFile(*configPath)
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
cfg, err := geoip.ParseConf(string(data))
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err) fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1) os.Exit(1)

View File

@ -2,8 +2,7 @@ package geoip
import ( import (
"bufio" "bufio"
"fmt" "errors"
"os"
"strings" "strings"
) )
@ -15,18 +14,16 @@ type Conf struct {
DatabaseDirectory string DatabaseDirectory string
} }
// ParseConf reads a geoipupdate-style config file (whitespace-separated // ErrMissingCredentials is returned by ParseConf when AccountID or LicenseKey
// key/value pairs, # comments). Compatible with GeoIP.conf files used by // is absent from the input.
// the official geoipupdate tool. var ErrMissingCredentials = errors.New("AccountID and LicenseKey are required")
func ParseConf(path string) (*Conf, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
// ParseConf parses a geoipupdate-style config (whitespace-separated key/value
// pairs, # comments). Compatible with GeoIP.conf files used by the official
// geoipupdate tool.
func ParseConf(s string) (*Conf, error) {
kv := make(map[string]string) kv := make(map[string]string)
scanner := bufio.NewScanner(f) scanner := bufio.NewScanner(strings.NewReader(s))
for scanner.Scan() { for scanner.Scan() {
line := strings.TrimSpace(scanner.Text()) line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") { if line == "" || strings.HasPrefix(line, "#") {
@ -45,7 +42,7 @@ func ParseConf(path string) (*Conf, error) {
DatabaseDirectory: kv["DatabaseDirectory"], DatabaseDirectory: kv["DatabaseDirectory"],
} }
if c.AccountID == "" || c.LicenseKey == "" { if c.AccountID == "" || c.LicenseKey == "" {
return nil, fmt.Errorf("AccountID and LicenseKey are required in %s", path) return nil, ErrMissingCredentials
} }
if ids := kv["EditionIDs"]; ids != "" { if ids := kv["EditionIDs"]; ids != "" {
c.EditionIDs = strings.Fields(ids) c.EditionIDs = strings.Fields(ids)

View File

@ -31,8 +31,8 @@ func geoipConf(t *testing.T) *geoip.Conf {
dir, _ := filepath.Abs(".") dir, _ := filepath.Abs(".")
for { for {
p := filepath.Join(dir, "GeoIP.conf") p := filepath.Join(dir, "GeoIP.conf")
if _, err := os.Stat(p); err == nil { if data, err := os.ReadFile(p); err == nil {
cfg, err := geoip.ParseConf(p) cfg, err := geoip.ParseConf(string(data))
if err != nil { if err != nil {
t.Fatalf("GeoIP.conf: %v", err) t.Fatalf("GeoIP.conf: %v", err)
} }