CoolFace
Apppublic

hake89/openclaw-cf2

sourceHugging Facemitupdated 7mo agoView on Hugging Face
0likes
dns-fix.cjs130 linesDownload Raw Back to scripts
1/**2 * DNS fix preload script for HF Spaces.3 *4 * Patches Node.js dns.lookup to:5 * 1. Check pre-resolved domains from /tmp/dns-resolved.json (populated by dns-resolve.py)6 * 2. Fall back to DNS-over-HTTPS (Cloudflare) for any other unresolvable domain7 *8 * Loaded via: NODE_OPTIONS="--require /path/to/dns-fix.cjs"9 */10"use strict";11 12const dns = require("dns");13const https = require("https");14const fs = require("fs");15 16// ── Pre-resolved domains (populated by entrypoint.sh via dns-resolve.py) ──17let preResolved = {};18try {19  const raw = fs.readFileSync("/tmp/dns-resolved.json", "utf8");20  preResolved = JSON.parse(raw);21  const count = Object.keys(preResolved).length;22  if (count > 0) {23    console.log(`[dns-fix] Loaded ${count} pre-resolved domains`);24  }25} catch {26  // File not found or parse error — proceed without pre-resolved cache27}28 29// ── In-memory cache for runtime DoH resolutions ──30const runtimeCache = new Map(); // hostname -> { ip, expiry }31 32// ── DNS-over-HTTPS resolver ──33function dohResolve(hostname, callback) {34  // Check runtime cache35  const cached = runtimeCache.get(hostname);36  if (cached && cached.expiry > Date.now()) {37    return callback(null, cached.ip);38  }39 40  const url = `https://1.1.1.1/dns-query?name=${encodeURIComponent(hostname)}&type=A`;41  const req = https.get(42    url,43    { headers: { Accept: "application/dns-json" }, timeout: 15000 },44    (res) => {45      let body = "";46      res.on("data", (c) => (body += c));47      res.on("end", () => {48        try {49          const data = JSON.parse(body);50          const aRecords = (data.Answer || []).filter((a) => a.type === 1);51          if (aRecords.length === 0) {52            return callback(new Error(`DoH: no A record for ${hostname}`));53          }54          const ip = aRecords[0].data;55          const ttl = Math.max((aRecords[0].TTL || 300) * 1000, 60000);56          runtimeCache.set(hostname, { ip, expiry: Date.now() + ttl });57          callback(null, ip);58        } catch (e) {59          callback(new Error(`DoH parse error: ${e.message}`));60        }61      });62    }63  );64  req.on("error", (e) => callback(new Error(`DoH request failed: ${e.message}`)));65  req.on("timeout", () => {66    req.destroy();67    callback(new Error("DoH request timed out"));68  });69}70 71// ── Monkey-patch dns.lookup ──72const origLookup = dns.lookup;73 74dns.lookup = function patchedLookup(hostname, options, callback) {75  // Normalize arguments (options is optional, can be number or object)76  if (typeof options === "function") {77    callback = options;78    options = {};79  }80  if (typeof options === "number") {81    options = { family: options };82  }83  options = options || {};84 85  // Skip patching for localhost, IPs, and internal domains86  if (87    !hostname ||88    hostname === "localhost" ||89    hostname === "0.0.0.0" ||90    hostname === "127.0.0.1" ||91    hostname === "::1" ||92    /^\d+\.\d+\.\d+\.\d+$/.test(hostname) ||93    /^::/.test(hostname)94  ) {95    return origLookup.call(dns, hostname, options, callback);96  }97 98  // 1) Check pre-resolved cache99  if (preResolved[hostname]) {100    const ip = preResolved[hostname];101    if (options.all) {102      return process.nextTick(() => callback(null, [{ address: ip, family: 4 }]));103    }104    return process.nextTick(() => callback(null, ip, 4));105  }106 107  // 2) Try system DNS108  origLookup.call(dns, hostname, options, (err, address, family) => {109    if (!err && address) {110      return callback(null, address, family);111    }112 113    // 3) System DNS failed with ENOTFOUND — fall back to DoH114    if (err && (err.code === "ENOTFOUND" || err.code === "EAI_AGAIN")) {115      dohResolve(hostname, (dohErr, ip) => {116        if (dohErr || !ip) {117          return callback(err); // Return original error118        }119        if (options.all) {120          return callback(null, [{ address: ip, family: 4 }]);121        }122        callback(null, ip, 4);123      });124    } else {125      // Other DNS errors — pass through126      callback(err, address, family);127    }128  });129};130