Resolve relative node logo paths before swarm announcements
Hop-State: A_06FP959CFWNA2D273CCHP4R Hop-Proposal: R_06FP957R3SZA57Z7S68VGSG Hop-Task: T_06FP94T21NC8DA4KTNYN5A8 Hop-Attempt: AT_06FP94T21QZ7GXMYNEQH85G
This commit is contained in:
@@ -12,19 +12,11 @@ import {
|
||||
getCanonicalSwarmSeedDomain,
|
||||
getPublicSwarmDomain,
|
||||
isPublicSwarmDomain,
|
||||
resolveNodeAssetUrl,
|
||||
} from './node-domain';
|
||||
|
||||
const PUBLIC_SWARM_DOMAIN_ERROR = 'Public swarm participation requires a real ICANN domain';
|
||||
|
||||
function normalizeOptionalUrl(value: string | null | undefined): string | undefined {
|
||||
if (!value) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build this node's announcement payload
|
||||
*/
|
||||
@@ -48,7 +40,7 @@ export async function buildAnnouncement(): Promise<SwarmAnnouncement> {
|
||||
if (node) {
|
||||
name = node.name;
|
||||
description = node.description ?? undefined;
|
||||
logoUrl = normalizeOptionalUrl(node.logoUrl);
|
||||
logoUrl = resolveNodeAssetUrl(node.logoUrl, domain);
|
||||
publicKey = node.publicKey ?? '';
|
||||
isNsfw = node.isNsfw;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
getCanonicalSwarmSeedDomain,
|
||||
getPublicSwarmDomain,
|
||||
isPublicSwarmDomain,
|
||||
resolveNodeAssetUrl,
|
||||
} from './node-domain';
|
||||
|
||||
describe('public swarm domains', () => {
|
||||
@@ -49,3 +50,17 @@ describe('swarm seed domains', () => {
|
||||
expect(getCanonicalSwarmSeedDomain('localhost:43821')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('node asset URLs', () => {
|
||||
it('resolves a relative logo path against the node domain', () => {
|
||||
expect(
|
||||
resolveNodeAssetUrl('/api/node/logo?v=1784095823196', 'batorbros.bond')
|
||||
).toBe('https://batorbros.bond/api/node/logo?v=1784095823196');
|
||||
});
|
||||
|
||||
it('preserves an absolute HTTPS asset URL', () => {
|
||||
expect(
|
||||
resolveNodeAssetUrl('https://media.example.org/node/logo.png', 'batorbros.bond')
|
||||
).toBe('https://media.example.org/node/logo.png');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -56,6 +56,23 @@ export function isPublicSwarmDomain(value: string | null | undefined): boolean {
|
||||
return getPublicSwarmDomain(value) !== null;
|
||||
}
|
||||
|
||||
export function resolveNodeAssetUrl(
|
||||
value: string | null | undefined,
|
||||
nodeDomain: string
|
||||
): string | undefined {
|
||||
const trimmed = value?.trim();
|
||||
if (!trimmed) return undefined;
|
||||
|
||||
try {
|
||||
const resolved = new URL(trimmed, `https://${normalizeNodeDomain(nodeDomain)}`);
|
||||
return resolved.protocol === 'http:' || resolved.protocol === 'https:'
|
||||
? resolved.toString()
|
||||
: undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve retired bootstrap hostnames to the node identity they represent.
|
||||
* This keeps upgraded nodes working even before their persisted seed rows are
|
||||
|
||||
Reference in New Issue
Block a user