Address codex review (#22): client IP validation, updated_at, merge robustness
1. /json client IP (codex #1, Medium): HandleJson now validates
c.ClientIP() and returns 400 on a malformed value instead of letting
Query fail into a 500. HandleIpInfo gained a selfLookup flag so a valid
but DB-absent self-IP preserves the 9d07639 graceful 200 {"ip": ip}
default (private/loopback addresses are never in a public GeoIP DB),
while the explicit /:ip route still returns 404 on not-found.
2. updated_at=0 on initial load (codex #2, Low): stampDbUpdatedAt() now
records the canonical mmdb's mtime both on initial load (existing
files) and after each successful update, so /metrics never reports 0
while serving real data.
3. Merge corruption -> permanent outage: mmdbmeld.WriteMMDB truncates the
canonical mmdb before writing; a failed merge previously left it empty
and the saved etag made the next daily run 304-skip the retry, so a
restart failed to open the file and the service went 503 permanently.
fetchDbs now backs up the canonical file before merge, restores it on
merge/reload failure, and drops the etags so the next run retries.
4. Temp-file leaks: Reload removes the temp clone and restores d.dbFile
when reader.Open fails (it previously assigned d.dbFile before Open);
cloneDBFile removes the temp on a failed copy.
Verified: go build, go vet, gofmt -l, go test -race ./... all pass.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -83,7 +83,11 @@ func (d *IpDb) Reload() error {
|
||||
d.dbFile = tmpFile
|
||||
r, err := reader.Open(tmpFile)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to open mmdb")
|
||||
log.Err(err).Str("file", tmpFile).Msg("Failed to open mmdb")
|
||||
// Open failed: drop the orphaned temp clone and leave d.dbFile/d.r
|
||||
// pointing at the previously loaded DB.
|
||||
_ = os.Remove(tmpFile)
|
||||
d.dbFile = wilDeleteFile
|
||||
return err
|
||||
}
|
||||
log.Info().Str("file", tmpFile).Msg("MMDB reloaded")
|
||||
@@ -127,6 +131,8 @@ func cloneDBFile() (string, error) {
|
||||
// Copy the data from srcFile to dstFile
|
||||
_, err = io.CopyBuffer(tmpFile, srcFile, buf)
|
||||
if err != nil {
|
||||
// Leave nothing behind on a failed copy.
|
||||
_ = os.Remove(tmpFile.Name())
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user