fix(worker): omit Globalping ipVersion for IP targets (#177)

Globalping rejects measurementOptions.ipVersion when the measurement target is an IP address.
Add an IP-target guard so ipVersion is only sent for domain targets, preventing validation errors when checking IP:port monitors.
pull/180/head
KebenSun 2026-01-17 03:00:49 +09:00 committed by GitHub
parent da4bfb888d
commit 5512912b22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 2 deletions

View File

@ -1,6 +1,28 @@
import { MonitorTarget } from '../../types/config' import { MonitorTarget } from '../../types/config'
import { withTimeout, fetchTimeout } from './util' import { withTimeout, fetchTimeout } from './util'
function isIpAddress(hostname: string): boolean {
// `URL.hostname` strips brackets for IPv6, so a `:` reliably indicates an IPv6 literal here.
if (hostname.includes(':')) return true
const parts = hostname.split('.')
if (parts.length !== 4) return false
return parts.every((part) => {
if (!/^\d{1,3}$/.test(part)) return false
const value = Number(part)
return value >= 0 && value <= 255
})
}
function getDomainOnlyIpVersionOption(hostname: string, gpUrl: URL): { ipVersion?: number } {
// Globalping only allows `measurementOptions.ipVersion` when `target` is a domain (it controls DNS resolution).
if (isIpAddress(hostname)) return {}
// Keep the original behavior for domain targets.
return { ipVersion: Number(gpUrl.searchParams.get('ipVersion') || 4) }
}
async function httpResponseBasicCheck( async function httpResponseBasicCheck(
monitor: MonitorTarget, monitor: MonitorTarget,
code: number, code: number,
@ -66,6 +88,7 @@ export async function getStatusWithGlobalPing(
if (monitor.method === 'TCP_PING') { if (monitor.method === 'TCP_PING') {
const targetUrl = new URL('https://' + monitor.target) // dummy https:// to parse hostname & port const targetUrl = new URL('https://' + monitor.target) // dummy https:// to parse hostname & port
const ipVersionOption = getDomainOnlyIpVersionOption(targetUrl.hostname, gpUrl)
globalPingRequest = { globalPingRequest = {
type: 'ping', type: 'ping',
target: targetUrl.hostname, target: targetUrl.hostname,
@ -81,11 +104,12 @@ export async function getStatusWithGlobalPing(
port: targetUrl.port, port: targetUrl.port,
packets: 1, packets: 1,
protocol: 'tcp', // TODO: icmp? protocol: 'tcp', // TODO: icmp?
ipVersion: Number(gpUrl.searchParams.get('ipVersion') || 4), ...ipVersionOption,
}, },
} }
} else { } else {
const targetUrl = new URL(monitor.target) const targetUrl = new URL(monitor.target)
const ipVersionOption = getDomainOnlyIpVersionOption(targetUrl.hostname, gpUrl)
if (monitor.body !== undefined) { if (monitor.body !== undefined) {
throw 'custom body not supported' throw 'custom body not supported'
} }
@ -119,7 +143,7 @@ export async function getStatusWithGlobalPing(
: 443 : 443
: Number(targetUrl.port), : Number(targetUrl.port),
protocol: targetUrl.protocol.replace(':', ''), protocol: targetUrl.protocol.replace(':', ''),
ipVersion: Number(gpUrl.searchParams.get('ipVersion') || 4), ...ipVersionOption,
}, },
} }
} }