diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index 2aea8e73c..8035d92c0 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -20,6 +20,7 @@ interface FailoverHost { preferred?: boolean, checked: boolean, lastChecked?: number, + publicDomain: string, hashes: { frontend?: string, backend?: string, @@ -58,6 +59,7 @@ class FailoverRouter { rtts: [], rtt: Infinity, failures: 0, + publicDomain: 'https://' + this.extractPublicDomain(domain), hashes: { lastUpdated: 0, }, @@ -71,6 +73,7 @@ class FailoverRouter { socket: !!config.ESPLORA.UNIX_SOCKET_PATH, preferred: true, checked: false, + publicDomain: `http://${this.localHostname}`, hashes: { lastUpdated: 0, }, @@ -242,7 +245,7 @@ class FailoverRouter { // methods for retrieving git hashes by host private async $updateFrontendGitHash(host: FailoverHost): Promise { try { - const url = host.socket ? `http://${this.localHostname}/resources/config.js` : `${host.host.slice(0, -4)}/resources/config.js`; + const url = `${host.publicDomain}/resources/config.js`; const response = await this.pollConnection.get(url, { timeout: config.ESPLORA.FALLBACK_TIMEOUT }); const match = response.data.match(/GIT_COMMIT_HASH\s*=\s*['"](.*?)['"]/); if (match && match[1]?.length) { @@ -255,7 +258,7 @@ class FailoverRouter { private async $updateBackendGitHash(host: FailoverHost): Promise { try { - const url = host.socket ? `http://${this.localHostname}/api/v1/backend-info` : `${host.host}/v1/backend-info`; + const url = `${host.publicDomain}/api/v1/backend-info`; const response = await this.pollConnection.get(url, { timeout: config.ESPLORA.FALLBACK_TIMEOUT }); if (response.data?.gitCommit) { host.hashes.backend = response.data.gitCommit; @@ -265,6 +268,21 @@ class FailoverRouter { } } + // returns the public mempool domain corresponding to an esplora server url + // (a bit of a hack to avoid manually specifying frontend & backend URLs for each esplora server) + private extractPublicDomain(url: string): string { + // force the url to start with a valid protocol + const urlWithProtocol = url.startsWith('http') ? url : `https://${url}`; + // parse as URL and extract the hostname + try { + const parsed = new URL(urlWithProtocol); + return parsed.hostname; + } catch (e) { + // fallback to the original url + return url; + } + } + private async $query(method: 'get'| 'post', path, data: any, responseType = 'json', host = this.activeHost, retry: boolean = true): Promise { let axiosConfig; let url;