fix hns resolver

This commit is contained in:
Karol Wypchlo 2020-07-31 00:50:20 +02:00
parent 02b77cfbab
commit b70d4f143e
1 changed files with 38 additions and 20 deletions

View File

@ -1,3 +1,4 @@
const url = require("url");
const express = require("express"); const express = require("express");
const proxy = require("express-http-proxy"); const proxy = require("express-http-proxy");
const { NodeClient } = require("hs-client"); const { NodeClient } = require("hs-client");
@ -18,14 +19,15 @@ const clientOptions = {
}; };
const client = new NodeClient(clientOptions); const client = new NodeClient(clientOptions);
const resolveDomain = async (name) => { const startsWithSkylinkRegExp = /^[a-zA-Z0-9_-]{46}/;
const getDomainRecords = async (name) => {
const response = await client.execute("getnameresource", [name]); const response = await client.execute("getnameresource", [name]);
const records = response?.records ?? null;
if (!response) throw new Error("API not responding"); console.log(`${name} => ${JSON.stringify(records)}`);
console.log(`${name} => ${JSON.stringify(response.records)}`); return records;
return response;
}; };
const findSkylinkRecord = (records) => { const findSkylinkRecord = (records) => {
@ -38,9 +40,12 @@ const getSkylinkFromRecord = (record) => {
const resolveDomainHandler = async (req, res) => { const resolveDomainHandler = async (req, res) => {
try { try {
const response = await resolveDomain(req.params.name); const records = await getDomainRecords(req.params.name);
const record = findSkylinkRecord(response.records); if (!records) return res.status(404).send(`No records found for ${req.params.name}`);
if (!record) return res.status(404).send(`No skylink found for ${req.params.name}`);
const record = findSkylinkRecord(records);
if (!record) throw new Error(`No skylink found in dns records of ${req.params.name}`);
const skylink = getSkylinkFromRecord(record); const skylink = getSkylinkFromRecord(record);
return res.json({ skylink }); return res.json({ skylink });
} catch (error) { } catch (error) {
@ -48,14 +53,12 @@ const resolveDomainHandler = async (req, res) => {
} }
}; };
const SIA_LINK_RE = /^([a-zA-Z0-9-_]{46}.*)$/;
// Checks if the given string is a valid Sia link. // Checks if the given string is a valid Sia link.
function isValidSkylink(link) { function isValidSkylink(link) {
if (!link || link.length === 0) { if (!link || link.length === 0) {
return false; return false;
} }
return Boolean(link.match(SIA_LINK_RE)); return Boolean(link.match(startsWithSkylinkRegExp));
} }
const server = express(); const server = express();
@ -63,19 +66,34 @@ const server = express();
server.use( server.use(
"/hns/:name", "/hns/:name",
proxy("nginx", { proxy("nginx", {
// eslint-disable-next-line no-unused-vars
userResHeaderDecorator(headers, userReq, userRes, proxyReq, proxyRes) {
if (headers.location && headers.location.match(startsWithSkylinkRegExp)) {
headers.location = headers.location.replace(startsWithSkylinkRegExp, `/hns/${userReq.params.name}`);
}
return headers;
},
proxyReqPathResolver: async (req) => { proxyReqPathResolver: async (req) => {
const response = await resolveDomain(req.params.name); const records = await getDomainRecords(req.params.name);
const record = findSkylinkRecord(response.records); if (!records) throw new Error(`No records found for ${req.params.name}`);
if (!record) throw new Error(`No skylink found for ${req.params.name}`);
const record = findSkylinkRecord(records);
if (!record) throw new Error(`No skylink found in dns records of ${req.params.name}`);
const skylink = getSkylinkFromRecord(record); const skylink = getSkylinkFromRecord(record);
const basepath = url.resolve("/", skylink); // make the url absolute
const subpath = req.url.slice(1); // drop the leading slash
// if this is exact domain call, do not append anything to skylink entry // if the skylink from handshake does not contain a subpath but subpath
if (req.url === "" || req.url === "/") return `/${skylink}`; // is defined in request, join the skylink and subpath together (do not
// use url.resolve because it will replace skylink with subapth thinking
// it is relative)
if (skylink.length === 46 && subpath) {
return `${basepath}/${subpath}`;
}
// drop any index.html or trailing slash from the skylink entry return url.resolve(basepath, subpath);
const path = skylink.split("/").slice(0, -1).join("/");
return `/${path}${req.url}`;
}, },
}) })
); );