~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-iroh

iroh transport for atlibs hosts: com.fedfork.exec.iroh.connect in Rust (atlibs-host) and JavaScript

0
0
main
97 lines · 6.1 KB Raw History
// node --test js/fetch.test.mjs
// The iroh: fetcher against fake-bin/ssh (relay.mjs to a unix socket) and http-stub.mjs, no network: URL
// parsing, keep-alive reuse per (ref, socket), one relay per concurrent request, chunked and
// connection: close responses, a relay that dies before answering retried once, abort, and an idle relay
// never holding a host process up.
import assert from "node:assert/strict";
import { execFile, spawn } from "node:child_process";
import { mkdtemp, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { after, before, test } from "node:test";
import { promisify } from "node:util";

import { SHELL_SOCKET, fetchers, irohFetch, irohUrl, relayCommand } from "./index.js";

const FAKE = new URL("./fake-bin/", import.meta.url).pathname;
const dir = await mkdtemp(join(tmpdir(), "atlibs-iroh-fetch-"));
const key = join(dir, "key");
await writeFile(key, "not a real key\n", { mode: 0o600 });
const sock = join(dir, "it's.sock"); // a quote: the relay command's quoting
const hostKeys = [{ type: "ssh-ed25519", publicKey: "AAAAC3Bare" }];
const ref = (r) => Buffer.from(JSON.stringify(r)).toString("base64url");
const base = `iroh:///${ref({ ticket: "abc123", hostKeys })}/${encodeURIComponent(sock)}`;
const spawned = [];
const fetch = irohFetch({ key, spawn: (cmd, args, options) => (spawned.push(args), spawn(join(FAKE, cmd), args, options)) });
const json = async (request) => {
	const r = await fetch(request);
	return { ...r, json: JSON.parse(r.body) };
};
let stub;

before(async () => {
	stub = spawn(process.execPath, [join(FAKE, "http-stub.mjs"), sock], { stdio: ["ignore", "pipe", "inherit"] });
	await new Promise((resolve) => stub.stdout.once("data", resolve));
});
after(() => (fetch.close(), stub.kill()));

test("irohUrl: ref, socket (shell alias or a percent-encoded path), target", () => {
	assert.deepEqual(irohUrl(`iroh:///${ref({ ticket: "iroh://abc", hostKeys })}/shell/mcp?x=1#f`), { ticket: "abc", hostKeys, socket: SHELL_SOCKET, target: "/mcp?x=1" });
	assert.deepEqual(irohUrl(`iroh://${ref({ ticket: "abc", hostKeys })}/%2Ftmp%2Fs.sock`), { ticket: "abc", hostKeys, socket: "/tmp/s.sock", target: "/" });
	assert.throws(() => irohUrl("iroh:///abc"), /not an iroh/);
	assert.throws(() => irohUrl(`iroh:///${ref({ ticket: "abc" })}/tmp/x`), /absolute unix path/);
	assert.throws(() => irohUrl(`iroh:///${ref({ ticket: "ABC" })}/shell/mcp`), /not an iroh ticket/);
	assert.throws(() => irohUrl(`iroh:///e30/shell/a b`), /spaces/);
	assert.throws(() => irohUrl("iroh:///!!/shell/mcp"), /not an iroh/);
	assert.equal(relayCommand("/a'b"), "socialweb-guest-agent relay '/a'\\''b'");
});

test("a POST through the relay; the next request reuses its connection", async () => {
	const r = await json({ method: "POST", url: `${base}/mcp`, headers: { "content-type": "application/json", accept: "application/json, text/event-stream", host: "evil" }, body: '{"jsonrpc":"2.0"}' });
	assert.equal(r.status, 200);
	assert.equal(r.headers["content-type"], "application/json");
	assert.deepEqual([r.json.method, r.json.url, r.json.body, r.json.headers.host, r.json.headers.accept, r.json.n], ["POST", "/mcp", '{"jsonrpc":"2.0"}', "guest", "application/json, text/event-stream", 1]);
	assert.deepEqual(spawned[0].slice(-3), ["--", "root@guest", relayCommand(sock)]);
	assert.ok(spawned[0].includes("StrictHostKeyChecking=yes") && spawned[0].includes("ProxyCommand=dumbpipe connect abc123"));
	const again = await json({ url: `${base}/x` });
	assert.deepEqual([again.json.method, again.json.n, spawned.length], ["GET", 2, 1], "keep-alive: the same relay");
});

test("concurrent requests get a relay each; chunked bodies; connection: close is not reused", async () => {
	const before = spawned.length;
	const [slow, fast] = await Promise.all([json({ url: `${base}/slow?ms=300` }), json({ url: `${base}/fast?chunked=1` })]);
	assert.deepEqual([slow.json.url, fast.json.url, fast.headers["transfer-encoding"]], ["/slow?ms=300", "/fast?chunked=1", "chunked"]);
	assert.equal(spawned.length, before + 1, "one more relay for the second in-flight request");
	await json({ url: `${base}/c?close=1` });
	await json({ url: `${base}/c?close=1` });
	await json({ url: `${base}/c?close=1` });
	assert.equal(spawned.length, before + 2, "the two idle relays, then a fresh one for the third");
});

test("a relay that dies before answering is retried once on a fresh one", async () => {
	const before = spawned.length;
	const r = await json({ method: "POST", url: `${base}/mcp?die=${encodeURIComponent(join(dir, "died"))}`, body: "{}" });
	assert.equal(r.json.n, 1, "answered on a new connection");
	assert.ok(spawned.length >= before + 1);
	await assert.rejects(fetch({ url: `iroh:///${ref({ ticket: "abc", hostKeys })}/${encodeURIComponent(join(dir, "absent.sock"))}/` }), /relay ended .*relay: connect ENOENT/s);
});

test("abort, bad input, a missing key", async () => {
	await assert.rejects(fetch({ url: `${base}/s?ms=2000`, signal: AbortSignal.timeout(200) }), { name: "TimeoutError" });
	await assert.rejects(fetch({ url: `iroh:///${ref({ ticket: "abc" })}/shell/mcp` }), /no host keys/);
	await assert.rejects(fetch({ url: `${base}/`, headers: { "x-a": "b\r\nx: y" } }), /bad header/);
	await assert.rejects(fetch({ method: "GE T", url: `${base}/` }), /bad method/);
	await assert.rejects(irohFetch({ key: join(dir, "absent") })({ url: `${base}/` }), /ATLIBS_IROH_KEY/);
	assert.equal(typeof fetchers({ env: {}, stateDir: dir })["iroh:"], "function");
});

test("an idle relay never keeps the host process up", async () => {
	const script = `import { spawn } from "node:child_process";
		import { irohFetch } from ${JSON.stringify(new URL("./index.js", import.meta.url).href)};
		const fetch = irohFetch({ key: ${JSON.stringify(key)}, spawn: (cmd, args, o) => spawn(${JSON.stringify(FAKE)} + cmd, args, o) });
		console.log((await fetch({ url: ${JSON.stringify(`${base}/idle`)} })).status);`;
	const started = Date.now();
	const { stdout } = await promisify(execFile)(process.execPath, ["--input-type=module", "-e", script], { timeout: 10000 });
	assert.equal(stdout.trim(), "200");
	assert.ok(Date.now() - started < 5000, "exited without waiting on the relay");
});