mirror of
https://github.com/DeNNiiInc/Web-Page-Performance-Test.git
synced 2026-04-18 12:05:59 +00:00
82 lines
2.6 KiB
JavaScript
82 lines
2.6 KiB
JavaScript
const { exec } = require('child_process');
|
|
const dns = require('dns');
|
|
|
|
/**
|
|
* Executes a traceroute to the specified host.
|
|
* @param {string} host - The hostname or IP to trace.
|
|
* @returns {Promise<string>} - The raw stdout output of the traceroute command.
|
|
*/
|
|
function runTraceroute(host) {
|
|
return new Promise((resolve, reject) => {
|
|
// Basic validation to prevent command injection
|
|
if (!/^[a-zA-Z0-9.-]+$/.test(host)) {
|
|
return reject(new Error('Invalid hostname format.'));
|
|
}
|
|
|
|
// Resolve domain to ensure it exists before running system command (optional safety)
|
|
dns.lookup(host, (err) => {
|
|
if (err) return reject(new Error(`Could not resolve host: ${host}`));
|
|
|
|
// Detect platform
|
|
const isWin = process.platform === 'win32';
|
|
const command = isWin ? `tracert -d -h 20 ${host}` : `traceroute -n -m 20 ${host}`;
|
|
|
|
exec(command, { timeout: 60000 }, (error, stdout, stderr) => {
|
|
if (error) {
|
|
// Traceroute might return error code if it doesn't reach dest, but stdout is valuable
|
|
if (stdout) resolve(stdout);
|
|
else reject(error || stderr);
|
|
} else {
|
|
resolve(stdout);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
const geoip = require('geoip-lite');
|
|
|
|
/**
|
|
* Parses traceroute output and adds geolocation data.
|
|
* @param {string} output - Raw traceroute output.
|
|
* @returns {Array} - Array of hop objects with IP, RTT, and Location.
|
|
*/
|
|
function parseAndLocate(output) {
|
|
const lines = output.split('\n');
|
|
const hops = [];
|
|
|
|
// Regex to match lines like: " 1 192.168.1.1 2.5 ms"
|
|
// Linux: 1 _gateway (10.0.2.2) 0.224 ms 0.180 ms 0.120 ms
|
|
// Windows: 1 <1 ms <1 ms <1 ms 192.168.1.1
|
|
const ipRegex = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/;
|
|
|
|
lines.forEach(line => {
|
|
const match = line.match(ipRegex);
|
|
if (match) {
|
|
const ip = match[0];
|
|
const geo = geoip.lookup(ip);
|
|
|
|
hops.push({
|
|
raw: line.trim(),
|
|
ip: ip,
|
|
lat: geo ? geo.ll[0] : null,
|
|
lon: geo ? geo.ll[1] : null,
|
|
city: geo ? geo.city : null,
|
|
country: geo ? geo.country : null
|
|
});
|
|
}
|
|
});
|
|
return hops;
|
|
}
|
|
|
|
/**
|
|
* Executes traceroute and returns structured data.
|
|
*/
|
|
async function traceAndLocate(host) {
|
|
const rawOutput = await runTraceroute(host);
|
|
const hops = parseAndLocate(rawOutput);
|
|
return { raw: rawOutput, hops };
|
|
}
|
|
|
|
module.exports = { runTraceroute, traceAndLocate };
|