Embeds a DB-IP Lite country MMDB (~5MB) in the binary via go:embed, keeping the single-binary deployment story clean. Country codes are stored alongside login attempts and sessions, shown in the dashboard (Top IPs, Top Countries card, Recent/Active Sessions, session detail). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
52 lines
1.0 KiB
Go
52 lines
1.0 KiB
Go
package geoip
|
|
|
|
import (
|
|
_ "embed"
|
|
"net"
|
|
|
|
"github.com/oschwald/maxminddb-golang"
|
|
)
|
|
|
|
//go:embed dbip-country-lite.mmdb
|
|
var mmdbData []byte
|
|
|
|
// Reader provides country-level GeoIP lookups using an embedded DB-IP Lite database.
|
|
type Reader struct {
|
|
db *maxminddb.Reader
|
|
}
|
|
|
|
// New opens the embedded MMDB and returns a ready-to-use Reader.
|
|
func New() (*Reader, error) {
|
|
db, err := maxminddb.FromBytes(mmdbData)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Reader{db: db}, nil
|
|
}
|
|
|
|
type countryRecord struct {
|
|
Country struct {
|
|
ISOCode string `maxminddb:"iso_code"`
|
|
} `maxminddb:"country"`
|
|
}
|
|
|
|
// Lookup returns the ISO 3166-1 alpha-2 country code for the given IP address,
|
|
// or an empty string if the lookup fails or no result is found.
|
|
func (r *Reader) Lookup(ipStr string) string {
|
|
ip := net.ParseIP(ipStr)
|
|
if ip == nil {
|
|
return ""
|
|
}
|
|
|
|
var record countryRecord
|
|
if err := r.db.Lookup(ip, &record); err != nil {
|
|
return ""
|
|
}
|
|
return record.Country.ISOCode
|
|
}
|
|
|
|
// Close releases resources held by the reader.
|
|
func (r *Reader) Close() error {
|
|
return r.db.Close()
|
|
}
|