admin/internet: faster
Massimo Melina committed
Aug 21, 2023 at 14:30 UTC
020483abdcec3a8747220d3651433ed245bcf670
1 file changed
+27
-18
src/api.net.ts
+27
-18
@@ -38,8 +38,15 @@ async function getNatInfo() {
38
39
async function getPublicIp() {
40
const prjInfo = await getProjectInfo()
41
- for (const url of _.shuffle(prjInfo.publicIpServices))
42
- try { return (await httpsString(url)).body?.trim() }
41
+ for (const urls of _.chunk(_.shuffle(prjInfo.publicIpServices), 2)) // small parallelization
42
+ try {
43
+ return await Promise.any(urls.map(url => httpsString(url).then(res => {
44
+ const ip = res.body?.trim()
45
+ if (!/[.:0-9a-fA-F]/.test(ip))
46
+ throw Error("bad result: " + ip)
47
+ return ip
48
+ })))
49
+ }
50
catch (e: any) { console.debug(String(e)) }
51
}
52
@@ -68,7 +75,6 @@ const apis: ApiHandlers = {
75
},
76
77
async check_server() {
71
- const noop = () => null
78
const { publicIp, internalPort, externalPort } = await getNatInfo()
79
if (!publicIp) return new ApiError(HTTP_SERVICE_UNAVAILABLE, 'cannot detect public ip')
80
const prjInfo = await getProjectInfo()
@@ -83,21 +89,24 @@ const apis: ApiHandlers = {
89
regexpFailure: string
90
regexpSuccess: string
91
}
86
- for (const svc of _.shuffle<PortScannerService>(prjInfo.checkServerServices)) {
87
- const service = new URL(svc.url).hostname
88
- console.log('using service', service)
89
- const api = (axios as any)[svc.method]
90
- const body = svc.body?.replace('$IP', publicIp).replace('$PORT', port) || ''
91
- const res = await api(svc.url, body, {headers: svc.headers}).catch(noop)
92
- if (!res) continue
93
- console.debug('service responded')
94
- const parsed = parse(res.data).querySelector(svc.selector)?.innerText
95
- if (!parsed) continue
96
- const success = new RegExp(svc.regexpSuccess).test(parsed)
97
- const failure = new RegExp(svc.regexpFailure).test(parsed)
98
- if (success === failure) continue // this result cannot be trusted
99
- console.log('server', success ? 'responding' : 'not responding')
100
- return { success, service }
92
+ for (const services of _.chunk(_.shuffle<PortScannerService>(prjInfo.checkServerServices), 2)) {
93
+ try {
94
+ return Promise.any(services.map(async svc => {
95
+ const service = new URL(svc.url).hostname
96
+ console.log('trying service', service)
97
+ const api = (axios as any)[svc.method]
98
+ const body = svc.body?.replace('$IP', publicIp).replace('$PORT', port) || ''
99
+ const res = await api(svc.url, body, {headers: svc.headers})
100
+ console.debug(service, 'responded')
101
+ const parsed = parse(res.data).querySelector(svc.selector)?.innerText
102
+ if (!parsed) throw console.debug('empty:' + service)
103
+ const success = new RegExp(svc.regexpSuccess).test(parsed)
104
+ const failure = new RegExp(svc.regexpFailure).test(parsed)
105
+ if (success === failure) throw console.debug('inconsistent:' + service) // this result cannot be trusted
106
+ return { success, service }
107
+ }))
108
+ }
109
+ catch {}
110
}
111
return new ApiError(HTTP_SERVICE_UNAVAILABLE, 'no service available to detect upnp mapping')
112
},