diff --git a/src/gateway/public-gateway.mjs b/src/gateway/public-gateway.mjs index b0cecd1..e0f3838 100644 --- a/src/gateway/public-gateway.mjs +++ b/src/gateway/public-gateway.mjs @@ -91,10 +91,45 @@ async function serve(res, name, reqPath, baseHref) { } catch (e) { res.writeHead(502); res.end("gateway error: " + e.message); } } +// Native BNS TLDs — never overlap ICANN, so hijacking them here is safe. +// Dual TLDs (.com, .de, .dev) always fall through to search, so a bare +// `github.com` in the URL bar keeps going to the real GitHub, not to a +// BNS registration that happens to share the name. +const NATIVE_TLDS = new Set(["bch", "p2p", "bit", "nav"]); + +// Universal "set-as-default-search-engine" shim. Users add +// https://navigate.st/search?q=%s +// as their browser's default search engine; typing `silentmode.bch` in the URL +// bar (which Chromium/Firefox otherwise send to Google as a search query +// because .bch isn't in ICANN's known-TLD list) arrives here. If q looks like +// a native BNS name we 302 to the relay (works in every browser, no local +// daemon needed); otherwise forward to DuckDuckGo so ordinary search still +// works. Even an unregistered native-TLD query goes to the relay so the user +// gets a clear NXDOMAIN page instead of a confusing search detour. +async function handleSearch(url, res) { + const q = (url.searchParams.get("q") || "").trim().toLowerCase(); + const bare = q.replace(/^[a-z]+:\/\//, "").split("/")[0]; + const m = bare.match(/^([a-z0-9-]+)\.([a-z0-9-]+)$/); + let target; + if (m && NATIVE_TLDS.has(m[2])) { + target = `https://navigate.st/bns/${m[1]}.${m[2]}/`; + } else { + target = `https://duckduckgo.com/?q=${encodeURIComponent(q)}`; + } + res.writeHead(302, { location: target }); + res.end(); +} + const server = http.createServer(async (req, res) => { try { const hostHeader = (req.headers.host || "").split(":")[0].toLowerCase(); + // --- smart search endpoint (default-search-engine shim) --- + if (req.url.startsWith("/search")) { + const u = new URL(req.url, "http://x"); + return handleSearch(u, res); + } + // --- registrar API: availability of a name --- // GET /api/name/ -> { name, tld, registered, records? } if (req.url.startsWith("/api/name/")) {