better error in case geo-db download fails
Massimo Melina committed
Sep 29, 2025 at 12:08 UTC
eebc0708eb3db25de34c7b9e4bb8a142608ec00a
2 files changed
+20
-15
src/geo.ts
+18
-13
@@ -41,20 +41,25 @@ async function checkFiles() {
41
const LOCAL_FILE = 'geo_ip.bin'
42
const TEMP = LOCAL_FILE + '.downloading'
43
const { mtime=0 } = await stat(LOCAL_FILE).catch(() => ({ mtime: 0 }))
44
+ const name = 'geo-ip db'
45
const now = Date.now()
45
- if (+mtime < now - 31 * DAY) { // month-old or non-existing
46
- console.log('downloading geo-ip db')
47
- await unzip(await httpStream(URL), path =>
48
- path.toUpperCase().endsWith(ZIP_FILE) && TEMP)
49
- if (await stat(TEMP))
50
- if (isOpen())
51
- ip2location.close()
52
- await unlink(LOCAL_FILE).catch(() => {})
53
- await rename(TEMP, LOCAL_FILE)
54
- ip2country.cache.clear?.()
55
- console.log('download geo-ip db completed')
56
- }
46
+ if (+mtime < now - 31 * DAY) // month-old or non-existing
47
+ try {
48
+ const req = await httpStream(URL)
49
+ console.log(`downloading ${name}`)
50
+ await unzip(req, path => path.toUpperCase().endsWith(ZIP_FILE) && TEMP)
51
+ await stat(TEMP) // check existence
52
+ if (isOpen())
53
+ ip2location.close()
54
+ await unlink(LOCAL_FILE).catch(() => {})
55
+ await rename(TEMP, LOCAL_FILE)
56
+ ip2country.cache.clear?.()
57
+ console.log(`${name} download completed`)
58
+ }
59
+ catch (e: any) {
60
+ console.error(`Failed to download ${name}${mtime ? ", falling back on old data" : ''}:`, e?.message || String(e))
61
+ }
62
else if (isOpen()) return
58
- console.debug('loading geo-ip db')
63
+ console.debug(`loading ${name}`)
64
ip2location.open(LOCAL_FILE) // using openAsync causes a DEP0137 error within 10 seconds
65
}
src/util-http.ts
+2
-2
@@ -32,7 +32,7 @@ export interface XRequestOptions extends https.RequestOptions {
32
}
33
34
export declare namespace httpStream { let defaultProxy: string | undefined }
35
-export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThrow, ...options }: XRequestOptions ={}) {
35
+export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThrow=true, ...options }: XRequestOptions ={}) {
36
const controller = new AbortController()
37
options.signal ??= controller.signal
38
return Object.assign(new Promise<IncomingMessage>(async (resolve, reject) => {
@@ -78,7 +78,7 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
78
if (v) jar[k] = v
79
else delete jar[k]
80
}
81
- if (!res.statusCode || (httpThrow ?? true) && res.statusCode >= 400)
81
+ if (!res.statusCode || httpThrow && res.statusCode >= 400)
82
return reject(new Error(String(res.statusCode), { cause: res }))
83
let r = res.headers.location
84
if (r && !noRedirect) {