Refactor VPN proxy client implementation
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import test from 'node:test';
|
||||
|
||||
import { createGatewayPresenceRoute } from '../../dist/server/http/routes/gatewayPresenceRoute.js';
|
||||
|
||||
const subscriptionUrl = 'https://subscription.example/0123456789abcdef0123456789abcdef';
|
||||
const nonce = '0123456789abcdef0123456789abcdef';
|
||||
|
||||
function response() {
|
||||
return {
|
||||
writeHead(status, headers) {
|
||||
this.status = status;
|
||||
this.headers = headers;
|
||||
},
|
||||
end(payload) {
|
||||
this.payload = JSON.parse(payload);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createHarness(overrides = {}) {
|
||||
const events = [];
|
||||
const route = createGatewayPresenceRoute({
|
||||
appMode: overrides.appMode || 'gateway',
|
||||
readState: () => {
|
||||
events.push('state');
|
||||
if (overrides.stateError) throw overrides.stateError;
|
||||
return { subscriptionUrl: overrides.subscriptionUrl ?? subscriptionUrl };
|
||||
},
|
||||
getHwid: () => {
|
||||
events.push('hwid');
|
||||
if (overrides.hwidError) throw overrides.hwidError;
|
||||
return overrides.gatewayId ?? 'gateway-1';
|
||||
},
|
||||
});
|
||||
return { route, events };
|
||||
}
|
||||
|
||||
test('Gateway presence route preserves query nonce, read order and raw response', async () => {
|
||||
const harness = createHarness();
|
||||
const res = response();
|
||||
assert.equal(await harness.route.handle({
|
||||
method: 'GET',
|
||||
url: `/api/gateway-presence?source=client&nonce=${nonce}&nonce=ignored`,
|
||||
}, res), true);
|
||||
assert.deepEqual(harness.events, ['state', 'hwid']);
|
||||
assert.equal(res.status, 200);
|
||||
assert.equal(res.headers['content-type'], 'application/json; charset=utf-8');
|
||||
assert.deepEqual({
|
||||
...res.payload,
|
||||
proof: '[proof]',
|
||||
}, {
|
||||
success: true,
|
||||
available: true,
|
||||
product: 'harbor',
|
||||
role: 'gateway',
|
||||
protocolVersion: 1,
|
||||
gatewayId: 'gateway-1',
|
||||
transparentRouting: true,
|
||||
proof: '[proof]',
|
||||
});
|
||||
assert.match(res.payload.proof, /^[a-f0-9]{64}$/);
|
||||
});
|
||||
|
||||
test('Gateway presence route preserves unavailable client and missing identity responses', async () => {
|
||||
for (const options of [
|
||||
{ appMode: 'client' },
|
||||
{ gatewayId: '' },
|
||||
{ subscriptionUrl: 'https://subscription.example/public-feed' },
|
||||
]) {
|
||||
const harness = createHarness(options);
|
||||
const res = response();
|
||||
await harness.route.handle({
|
||||
method: 'GET',
|
||||
url: `/api/gateway-presence?nonce=${nonce}`,
|
||||
}, res);
|
||||
assert.deepEqual(res.payload, {
|
||||
success: true,
|
||||
available: false,
|
||||
product: 'harbor',
|
||||
role: options.appMode || 'gateway',
|
||||
protocolVersion: 1,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('Gateway presence route reads state and HWID before preserving nonce validation errors', async () => {
|
||||
for (const value of [null, 'ABCDEF0123456789ABCDEF0123456789', 'short']) {
|
||||
const harness = createHarness();
|
||||
const url = value === null
|
||||
? '/api/gateway-presence'
|
||||
: `/api/gateway-presence?nonce=${value}`;
|
||||
await assert.rejects(
|
||||
harness.route.handle({ method: 'GET', url }, response()),
|
||||
(error) => error.code === 'REQUEST_INVALID',
|
||||
);
|
||||
assert.deepEqual(harness.events, ['state', 'hwid']);
|
||||
}
|
||||
});
|
||||
|
||||
test('Gateway presence route guards before dependencies and propagates dependency errors', async () => {
|
||||
for (const [method, url] of [
|
||||
['POST', `/api/gateway-presence?nonce=${nonce}`],
|
||||
['GET', `/api/gateway-presence/extra?nonce=${nonce}`],
|
||||
['GET', `/api/other?nonce=${nonce}`],
|
||||
]) {
|
||||
const harness = createHarness();
|
||||
assert.equal(await harness.route.handle({ method, url }, response()), false);
|
||||
assert.deepEqual(harness.events, []);
|
||||
}
|
||||
|
||||
const stateError = new Error('state failed');
|
||||
const brokenState = createHarness({ stateError });
|
||||
await assert.rejects(
|
||||
brokenState.route.handle({ method: 'GET', url: `/api/gateway-presence?nonce=${nonce}` }, response()),
|
||||
(error) => error === stateError,
|
||||
);
|
||||
assert.deepEqual(brokenState.events, ['state']);
|
||||
|
||||
const hwidError = new Error('hwid failed');
|
||||
const brokenHwid = createHarness({ hwidError });
|
||||
await assert.rejects(
|
||||
brokenHwid.route.handle({ method: 'GET', url: `/api/gateway-presence?nonce=${nonce}` }, response()),
|
||||
(error) => error === hwidError,
|
||||
);
|
||||
assert.deepEqual(brokenHwid.events, ['state', 'hwid']);
|
||||
});
|
||||
|
||||
test('Gateway presence route is the sole HTTP owner', () => {
|
||||
const index = readFileSync(new URL('../../src/server/index.ts', import.meta.url), 'utf8');
|
||||
const route = readFileSync(
|
||||
new URL('../../src/server/http/routes/gatewayPresenceRoute.ts', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
assert.match(index, /createGatewayPresenceRoute\(\{/);
|
||||
assert.match(index, /gatewayPresenceRoute\.handle\(req, res\)/);
|
||||
assert.doesNotMatch(index, /\/api\/gateway-presence|buildGatewayPresence|searchParams\.get\(['"]nonce/);
|
||||
assert.match(route, /buildGatewayPresence\(\{/);
|
||||
assert.match(route, /searchParams\.get\(['"]nonce['"]\)/);
|
||||
});
|
||||
Reference in New Issue
Block a user