diff --git a/backend/controllers/cln/channels.js b/backend/controllers/cln/channels.js index fb7a00e3..b9e0eece 100644 --- a/backend/controllers/cln/channels.js +++ b/backend/controllers/cln/channels.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { getAlias } from './network.js'; diff --git a/backend/controllers/cln/getInfo.js b/backend/controllers/cln/getInfo.js index 53a9101e..e8714c30 100644 --- a/backend/controllers/cln/getInfo.js +++ b/backend/controllers/cln/getInfo.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { CLWSClient } from './webSocketClient.js'; diff --git a/backend/controllers/cln/invoices.js b/backend/controllers/cln/invoices.js index 0ff81ff7..d1f04c1f 100644 --- a/backend/controllers/cln/invoices.js +++ b/backend/controllers/cln/invoices.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/cln/network.js b/backend/controllers/cln/network.js index c9170bcd..ae132580 100644 --- a/backend/controllers/cln/network.js +++ b/backend/controllers/cln/network.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/cln/offers.js b/backend/controllers/cln/offers.js index 13080bd9..09290695 100644 --- a/backend/controllers/cln/offers.js +++ b/backend/controllers/cln/offers.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { Database } from '../../utils/database.js'; diff --git a/backend/controllers/cln/onchain.js b/backend/controllers/cln/onchain.js index f4615442..37ca3e26 100644 --- a/backend/controllers/cln/onchain.js +++ b/backend/controllers/cln/onchain.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/cln/payments.js b/backend/controllers/cln/payments.js index 6a756a00..77573cad 100644 --- a/backend/controllers/cln/payments.js +++ b/backend/controllers/cln/payments.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { Database } from '../../utils/database.js'; diff --git a/backend/controllers/cln/peers.js b/backend/controllers/cln/peers.js index d362b286..4889d189 100644 --- a/backend/controllers/cln/peers.js +++ b/backend/controllers/cln/peers.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { getAlias } from './network.js'; diff --git a/backend/controllers/cln/utility.js b/backend/controllers/cln/utility.js index 5a10dcdc..964b8f34 100644 --- a/backend/controllers/cln/utility.js +++ b/backend/controllers/cln/utility.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; @@ -44,7 +44,7 @@ export const verifyMessage = (req, res, next) => { } options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/checkmessage'; options.body = req.body; - request.post(options, (error, response, body) => { + request.post(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body }); res.status(201).json(body); }).catch((errRes) => { diff --git a/backend/controllers/eclair/channels.js b/backend/controllers/eclair/channels.js index 7b883de7..ea433bc8 100644 --- a/backend/controllers/eclair/channels.js +++ b/backend/controllers/eclair/channels.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { createInvoiceRequestCall, listPendingInvoicesRequestCall } from './invoices.js'; @@ -68,7 +68,7 @@ export const getChannels = (req, res, next) => { } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Empty Channels List Received' }); - res.status(200).json([]); + return res.status(200).json([]); } }). catch((errRes) => { diff --git a/backend/controllers/eclair/fees.js b/backend/controllers/eclair/fees.js index 0b4f4018..a84f78b4 100644 --- a/backend/controllers/eclair/fees.js +++ b/backend/controllers/eclair/fees.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/eclair/getInfo.js b/backend/controllers/eclair/getInfo.js index 813baa53..b5092f9d 100644 --- a/backend/controllers/eclair/getInfo.js +++ b/backend/controllers/eclair/getInfo.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { ECLWSClient } from './webSocketClient.js'; diff --git a/backend/controllers/eclair/invoices.js b/backend/controllers/eclair/invoices.js index f3d48cd3..e960c299 100644 --- a/backend/controllers/eclair/invoices.js +++ b/backend/controllers/eclair/invoices.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/eclair/network.js b/backend/controllers/eclair/network.js index c9924fd4..0a18622e 100644 --- a/backend/controllers/eclair/network.js +++ b/backend/controllers/eclair/network.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/eclair/onchain.js b/backend/controllers/eclair/onchain.js index 858e3e0e..4c3cacdd 100644 --- a/backend/controllers/eclair/onchain.js +++ b/backend/controllers/eclair/onchain.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/eclair/payments.js b/backend/controllers/eclair/payments.js index 25f6d974..1f07ab0f 100644 --- a/backend/controllers/eclair/payments.js +++ b/backend/controllers/eclair/payments.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; @@ -96,7 +96,7 @@ export const queryPaymentRoute = (req, res, next) => { } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Empty Payment Route Information Received' }); - res.status(200).json({ routes: [] }); + return res.status(200).json({ routes: [] }); } }).catch((errRes) => { const err = common.handleError(errRes, 'Payments', 'Query Route Error', req.session.selectedNode); diff --git a/backend/controllers/eclair/peers.js b/backend/controllers/eclair/peers.js index c29f4e22..8584e178 100644 --- a/backend/controllers/eclair/peers.js +++ b/backend/controllers/eclair/peers.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; @@ -43,7 +43,7 @@ export const getPeers = (req, res, next) => { } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Empty Peers Received' }); - res.status(200).json([]); + return res.status(200).json([]); } }). catch((errRes) => { @@ -95,7 +95,7 @@ export const connectPeer = (req, res, next) => { }); } else { - res.status(201).json([]); + return res.status(201).json([]); } }).catch((errRes) => { const err = common.handleError(errRes, 'Peers', 'Connect Peer Error', req.session.selectedNode); diff --git a/backend/controllers/lnd/balance.js b/backend/controllers/lnd/balance.js index b49f7a02..4dcc5bfa 100644 --- a/backend/controllers/lnd/balance.js +++ b/backend/controllers/lnd/balance.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/channels.js b/backend/controllers/lnd/channels.js index 7e70360d..b6c19c1a 100644 --- a/backend/controllers/lnd/channels.js +++ b/backend/controllers/lnd/channels.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/channelsBackup.js b/backend/controllers/lnd/channelsBackup.js index 3df40e53..27ffa5af 100644 --- a/backend/controllers/lnd/channelsBackup.js +++ b/backend/controllers/lnd/channelsBackup.js @@ -1,6 +1,6 @@ import * as fs from 'fs'; import { sep } from 'path'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/fees.js b/backend/controllers/lnd/fees.js index 643a5e91..708a96e0 100644 --- a/backend/controllers/lnd/fees.js +++ b/backend/controllers/lnd/fees.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { getAllForwardingEvents } from './switch.js'; diff --git a/backend/controllers/lnd/getInfo.js b/backend/controllers/lnd/getInfo.js index dd846ee9..a83f7617 100644 --- a/backend/controllers/lnd/getInfo.js +++ b/backend/controllers/lnd/getInfo.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { LNDWSClient } from './webSocketClient.js'; diff --git a/backend/controllers/lnd/graph.js b/backend/controllers/lnd/graph.js index 7d008e40..f74d19a1 100644 --- a/backend/controllers/lnd/graph.js +++ b/backend/controllers/lnd/graph.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/invoices.js b/backend/controllers/lnd/invoices.js index d9a0de29..928007e8 100644 --- a/backend/controllers/lnd/invoices.js +++ b/backend/controllers/lnd/invoices.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; import { LNDWSClient } from './webSocketClient.js'; diff --git a/backend/controllers/lnd/message.js b/backend/controllers/lnd/message.js index 65a1328f..57219707 100644 --- a/backend/controllers/lnd/message.js +++ b/backend/controllers/lnd/message.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/newAddress.js b/backend/controllers/lnd/newAddress.js index b8857064..90aec06f 100644 --- a/backend/controllers/lnd/newAddress.js +++ b/backend/controllers/lnd/newAddress.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/payments.js b/backend/controllers/lnd/payments.js index 56814bf5..03343b90 100644 --- a/backend/controllers/lnd/payments.js +++ b/backend/controllers/lnd/payments.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/peers.js b/backend/controllers/lnd/peers.js index a5e2988f..917e910c 100644 --- a/backend/controllers/lnd/peers.js +++ b/backend/controllers/lnd/peers.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/switch.js b/backend/controllers/lnd/switch.js index a8571941..dceea934 100644 --- a/backend/controllers/lnd/switch.js +++ b/backend/controllers/lnd/switch.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/transactions.js b/backend/controllers/lnd/transactions.js index 2d23ba28..452f9333 100644 --- a/backend/controllers/lnd/transactions.js +++ b/backend/controllers/lnd/transactions.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/wallet.js b/backend/controllers/lnd/wallet.js index 800cde3a..e876d4a2 100644 --- a/backend/controllers/lnd/wallet.js +++ b/backend/controllers/lnd/wallet.js @@ -1,5 +1,5 @@ import atob from 'atob'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/lnd/webSocketClient.js b/backend/controllers/lnd/webSocketClient.js index 0519da4f..3271546a 100644 --- a/backend/controllers/lnd/webSocketClient.js +++ b/backend/controllers/lnd/webSocketClient.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import * as fs from 'fs'; import { join } from 'path'; import { Logger } from '../../utils/logger.js'; diff --git a/backend/controllers/shared/RTLConf.js b/backend/controllers/shared/RTLConf.js index f8c78b4f..21c296ed 100644 --- a/backend/controllers/shared/RTLConf.js +++ b/backend/controllers/shared/RTLConf.js @@ -3,7 +3,7 @@ import * as fs from 'fs'; import { sep } from 'path'; import ini from 'ini'; import parseHocon from 'hocon-parser'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Database } from '../../utils/database.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; diff --git a/backend/controllers/shared/boltz.js b/backend/controllers/shared/boltz.js index caa9d700..a1c69592 100644 --- a/backend/controllers/shared/boltz.js +++ b/backend/controllers/shared/boltz.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/controllers/shared/loop.js b/backend/controllers/shared/loop.js index 525b635d..72fecfb7 100644 --- a/backend/controllers/shared/loop.js +++ b/backend/controllers/shared/loop.js @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger } from '../../utils/logger.js'; import { Common } from '../../utils/common.js'; let options = null; diff --git a/backend/utils/common.js b/backend/utils/common.js index 50041c12..e8ec856b 100644 --- a/backend/utils/common.js +++ b/backend/utils/common.js @@ -2,7 +2,7 @@ import * as fs from 'fs'; import { join, dirname, isAbsolute, resolve, sep } from 'path'; import { fileURLToPath } from 'url'; import * as crypto from 'crypto'; -import request from 'request-promise'; +import request from './request.js'; import { Logger } from './logger.js'; export class CommonService { constructor() { diff --git a/backend/utils/request.js b/backend/utils/request.js new file mode 100644 index 00000000..7e36b907 --- /dev/null +++ b/backend/utils/request.js @@ -0,0 +1,80 @@ +import axios from 'axios'; +import * as https from 'https'; +// Drop-in replacement for the deprecated request-promise, backed by axios. +// Accepts the same options shape used across the controllers ({ url, baseUrl, +// uri, qs, form, body, headers, rejectUnauthorized, json }), resolves with the +// response body directly and rejects with a plain, serializable object that +// mirrors request-promise's StatusCodeError/RequestError shape expected by +// CommonService.handleError. Auth headers are intentionally excluded from the +// rejected error so they can never leak into logs or API error responses. +const insecureAgent = new https.Agent({ rejectUnauthorized: false }); +const buildConfig = (options, method) => { + const config = { + url: options.url && options.url !== '' ? options.url : options.uri, + method: method || options.method || 'GET', + headers: options.headers ? { ...options.headers } : {} + }; + if (options.baseUrl) { + config.baseURL = options.baseUrl; + } + if (options.qs && Object.keys(options.qs).length > 0) { + config.params = options.qs; + } + if (options.rejectUnauthorized === false) { + config.httpsAgent = insecureAgent; + } + if (options.form !== null && options.form !== undefined) { + if (typeof options.form === 'string') { + // Pre-encoded (or raw JSON string for LND's wallet endpoints), send as-is. + config.data = options.form; + } + else { + const params = new URLSearchParams(); + Object.entries(options.form).forEach(([key, value]) => { + if (value !== null && value !== undefined) { + params.append(key, String(value)); + } + }); + config.data = params; + } + config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + else if (options.body !== null && options.body !== undefined) { + config.data = options.body; + } + if (options.json !== true) { + // Callers without json: true (block explorer, currency rates) JSON.parse the body themselves. + config.responseType = 'text'; + config.transformResponse = [(data) => data]; + } + return config; +}; +const toRequestPromiseError = (err, config) => { + const errOptions = { url: config.url, method: config.method }; + if (err.response) { + return { + name: 'StatusCodeError', + statusCode: err.response.status, + message: err.response.status + ' - ' + JSON.stringify(err.response.data), + error: err.response.data, + options: errOptions + }; + } + const message = err.message && err.message !== '' ? err.message : err.code; + return { + name: 'RequestError', + message: message, + error: { code: err.code, message: message }, + options: errOptions + }; +}; +const call = (options, method) => { + const config = buildConfig(options, method); + return axios.request(config).then((response) => response.data).catch((err) => Promise.reject(toRequestPromiseError(err, config))); +}; +const request = (options) => call(options); +request.get = (options) => call(options, 'GET'); +request.post = (options) => call(options, 'POST'); +request.put = (options) => call(options, 'PUT'); +request.delete = (options) => call(options, 'DELETE'); +export default request; diff --git a/package-lock.json b/package-lock.json index 901116fc..04a74c4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,8 +29,6 @@ "otplib": "12.0.1", "pdfmake": "0.3.11", "process": "0.11.10", - "request": "2.88.2", - "request-promise": "4.2.6", "rxjs": "7.8.2", "sha256": "0.2.0", "socket.io-client": "4.8.3", @@ -7679,6 +7677,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" @@ -7720,6 +7719,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8" @@ -7800,6 +7800,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -7809,6 +7810,7 @@ "version": "1.13.2", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, "license": "MIT" }, "node_modules/axios": { @@ -7962,6 +7964,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" @@ -8026,12 +8029,6 @@ "node": ">=6.9.x" } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "license": "MIT" - }, "node_modules/bn.js": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.5.tgz", @@ -8586,6 +8583,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "dev": true, "license": "Apache-2.0" }, "node_modules/chalk": { @@ -9641,6 +9639,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -10017,6 +10016,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, "license": "MIT", "dependencies": { "jsbn": "~0.1.0", @@ -11083,12 +11083,14 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, "license": "MIT" }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -11134,6 +11136,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -11352,6 +11355,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -11558,6 +11562,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0" @@ -11692,6 +11697,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, "license": "ISC", "engines": { "node": ">=4" @@ -11702,6 +11708,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", + "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.3", @@ -11715,6 +11722,7 @@ "version": "6.15.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -11731,6 +11739,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/has": { @@ -12036,6 +12045,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, "license": "MIT", "dependencies": { "assert-plus": "^1.0.0", @@ -12554,6 +12564,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, "license": "MIT" }, "node_modules/is-unicode-supported": { @@ -12632,6 +12643,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, "license": "MIT" }, "node_modules/istanbul-lib-coverage": { @@ -12855,6 +12867,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, "license": "MIT" }, "node_modules/jsesc": { @@ -12891,6 +12904,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, "license": "(AFL-2.1 OR BSD-3-Clause)" }, "node_modules/json-schema-traverse": { @@ -12918,6 +12932,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, "license": "ISC" }, "node_modules/json5": { @@ -12986,6 +13001,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, "license": "MIT", "dependencies": { "assert-plus": "1.0.0", @@ -13847,6 +13863,7 @@ "version": "4.18.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, "license": "MIT" }, "node_modules/lodash.debounce": { @@ -15080,6 +15097,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "*" @@ -15656,6 +15674,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, "license": "MIT" }, "node_modules/picocolors": { @@ -16208,6 +16227,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -16220,6 +16240,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -16691,6 +16712,7 @@ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, "license": "Apache-2.0", "dependencies": { "aws-sign2": "~0.7.0", @@ -16718,44 +16740,11 @@ "node": ">= 6" } }, - "node_modules/request-promise": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.6.tgz", - "integrity": "sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==", - "deprecated": "request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", - "license": "ISC", - "dependencies": { - "bluebird": "^3.5.0", - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "license": "ISC", - "dependencies": { - "lodash": "^4.17.19" - }, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, "node_modules/request/node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -16770,6 +16759,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -16779,6 +16769,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -16791,6 +16782,7 @@ "version": "6.5.5", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.5.tgz", "integrity": "sha512-mzR4sElr1bfCaPJe7m8ilJ6ZXdDaGoObcYR0ZHSsktM/Lt21MVHj5De30GQH2eiZ1qGRTO7LCAzQsUeXTNexWQ==", + "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.6" @@ -18229,6 +18221,7 @@ "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, "license": "MIT", "dependencies": { "asn1": "~0.2.3", @@ -18285,15 +18278,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", - "license": "ISC", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -18675,6 +18659,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "psl": "^1.1.28", @@ -18688,6 +18673,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -18831,6 +18817,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -18843,6 +18830,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, "license": "Unlicense" }, "node_modules/type-check": { @@ -19111,6 +19099,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" @@ -19120,6 +19109,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -19146,6 +19136,7 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, "license": "MIT", "bin": { "uuid": "bin/uuid" @@ -19181,6 +19172,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, "engines": [ "node >=0.6.0" ], @@ -19195,6 +19187,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, "license": "MIT" }, "node_modules/vite": { diff --git a/package.json b/package.json index 06551302..4b4fc103 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,6 @@ "otplib": "12.0.1", "pdfmake": "0.3.11", "process": "0.11.10", - "request": "2.88.2", - "request-promise": "4.2.6", "rxjs": "7.8.2", "sha256": "0.2.0", "socket.io-client": "4.8.3", diff --git a/release-notes/Release-notes-0.15.9.md b/release-notes/Release-notes-0.15.9.md index d241f39d..7207b985 100644 --- a/release-notes/Release-notes-0.15.9.md +++ b/release-notes/Release-notes-0.15.9.md @@ -149,6 +149,31 @@ this release should add its entry under the appropriate section below. builds, and an end-to-end smoke test of the docker regtest fixture across LND, Core Lightning and Eclair (auth, getinfo, channel lists, and the WebSocket upgrade path). +- **Replace the deprecated `request`/`request-promise` HTTP stack with axios** + ([#TBD](https://github.com/Ride-The-Lightning/RTL/pull/TBD), part of + [#1634](https://github.com/Ride-The-Lightning/RTL/issues/1634)). + `request` has been deprecated and unmaintained since 2020 and carries an unfixable SSRF + advisory plus vulnerable pinned copies of `form-data` (critical), `qs`, `tough-cookie` and + `uuid` — 8 of the 13 production `npm audit` findings left after #1633, none fixable by a + version bump. All 36 backend files that imported `request-promise` (the LND, Core Lightning + and Eclair controllers, Boltz/Loop/RTLConf shared controllers, `common.ts` and the LND + websocket client) now go through a small compatibility wrapper (`server/utils/request.ts`) + backed by `axios` — already a production dependency, so nothing new is added. The wrapper + accepts the existing request-promise options (`qs`, `form` including pre-encoded string + bodies, `body`, `baseUrl`/`uri`, `rejectUnauthorized`, `json`), resolves with the response + body directly, and rejects with a plain object mirroring request-promise's + `StatusCodeError`/`RequestError` shape, so `CommonService.handleError`'s status-code and + message extraction (including the `ECONNREFUSED` → 503 mapping and Eclair's status-code + special case) behaves as before; auth headers are omitted from rejected errors so they + cannot leak into logs. Callers without `json: true` still receive the raw text body, and + LND's line-delimited `/v2/router/send` stream still surfaces as a string for the existing + parser. Production `npm audit` drops from 13 findings (2 critical) to 6 low, all in the + `crypto-browserify`/`elliptic` polyfill chain tracked in #1634. Verified end-to-end against + the docker regtest fixture: 43 API checks across all three implementations (reads, invoice + creation, a routed LND payment over the streaming endpoint, cross-implementation payments + from Core Lightning and Eclair, message sign/verify, channel backup to disk, bad-invoice + and node-unreachable error mapping) plus a clean lint and both production builds. + - **Rebuild the compiled CLN channels controller to match its source** ([#1631](https://github.com/Ride-The-Lightning/RTL/pull/1631)). The #1606 fix updated `server/controllers/cln/channels.ts` to mirror `peer_connected` onto the diff --git a/server/controllers/cln/channels.ts b/server/controllers/cln/channels.ts index 4a68624e..dce63045 100644 --- a/server/controllers/cln/channels.ts +++ b/server/controllers/cln/channels.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { getAlias } from './network.js'; diff --git a/server/controllers/cln/getInfo.ts b/server/controllers/cln/getInfo.ts index ac311a74..79b93384 100644 --- a/server/controllers/cln/getInfo.ts +++ b/server/controllers/cln/getInfo.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { CLWSClient, CLWebSocketClient } from './webSocketClient.js'; diff --git a/server/controllers/cln/invoices.ts b/server/controllers/cln/invoices.ts index 225ceeed..be729498 100644 --- a/server/controllers/cln/invoices.ts +++ b/server/controllers/cln/invoices.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/cln/network.ts b/server/controllers/cln/network.ts index 6abcc281..8a107c96 100644 --- a/server/controllers/cln/network.ts +++ b/server/controllers/cln/network.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/cln/offers.ts b/server/controllers/cln/offers.ts index a515db41..9662c1e8 100644 --- a/server/controllers/cln/offers.ts +++ b/server/controllers/cln/offers.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { Database, DatabaseService } from '../../utils/database.js'; diff --git a/server/controllers/cln/onchain.ts b/server/controllers/cln/onchain.ts index 0495499b..d7cce50c 100644 --- a/server/controllers/cln/onchain.ts +++ b/server/controllers/cln/onchain.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/cln/payments.ts b/server/controllers/cln/payments.ts index fbf424aa..9553af31 100644 --- a/server/controllers/cln/payments.ts +++ b/server/controllers/cln/payments.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { Database, DatabaseService } from '../../utils/database.js'; diff --git a/server/controllers/cln/peers.ts b/server/controllers/cln/peers.ts index ff6b75f8..8106bbb4 100644 --- a/server/controllers/cln/peers.ts +++ b/server/controllers/cln/peers.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { getAlias } from './network.js'; diff --git a/server/controllers/cln/utility.ts b/server/controllers/cln/utility.ts index 2949d40d..dbcb8bca 100644 --- a/server/controllers/cln/utility.ts +++ b/server/controllers/cln/utility.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; @@ -42,7 +42,7 @@ export const verifyMessage = (req, res, next) => { if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); } options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/checkmessage'; options.body = req.body; - request.post(options, (error, response, body) => { + request.post(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Message', msg: 'Message Verified', data: body }); res.status(201).json(body); }).catch((errRes) => { diff --git a/server/controllers/eclair/channels.ts b/server/controllers/eclair/channels.ts index 733ad381..b6e9d8c5 100644 --- a/server/controllers/eclair/channels.ts +++ b/server/controllers/eclair/channels.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; @@ -68,7 +68,7 @@ export const getChannels = (req, res, next) => { }); } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Empty Channels List Received' }); - res.status(200).json([]); + return res.status(200).json([]); } }). catch((errRes) => { diff --git a/server/controllers/eclair/fees.ts b/server/controllers/eclair/fees.ts index afd2b2ed..19a25f4f 100644 --- a/server/controllers/eclair/fees.ts +++ b/server/controllers/eclair/fees.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/eclair/getInfo.ts b/server/controllers/eclair/getInfo.ts index 67f6c0de..3fda9d46 100644 --- a/server/controllers/eclair/getInfo.ts +++ b/server/controllers/eclair/getInfo.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { ECLWSClient, ECLWebSocketClient } from './webSocketClient.js'; diff --git a/server/controllers/eclair/invoices.ts b/server/controllers/eclair/invoices.ts index 372b4c24..a6f80ab5 100644 --- a/server/controllers/eclair/invoices.ts +++ b/server/controllers/eclair/invoices.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/eclair/network.ts b/server/controllers/eclair/network.ts index a9cf0736..ac89a89b 100644 --- a/server/controllers/eclair/network.ts +++ b/server/controllers/eclair/network.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/eclair/onchain.ts b/server/controllers/eclair/onchain.ts index 4da0b24a..b2f9b001 100644 --- a/server/controllers/eclair/onchain.ts +++ b/server/controllers/eclair/onchain.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/eclair/payments.ts b/server/controllers/eclair/payments.ts index 80339325..921f386e 100644 --- a/server/controllers/eclair/payments.ts +++ b/server/controllers/eclair/payments.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; @@ -89,7 +89,7 @@ export const queryPaymentRoute = (req, res, next) => { }); } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Payments', msg: 'Empty Payment Route Information Received' }); - res.status(200).json({ routes: [] }); + return res.status(200).json({ routes: [] }); } }).catch((errRes) => { const err = common.handleError(errRes, 'Payments', 'Query Route Error', req.session.selectedNode); diff --git a/server/controllers/eclair/peers.ts b/server/controllers/eclair/peers.ts index 2690774d..a0712a75 100644 --- a/server/controllers/eclair/peers.ts +++ b/server/controllers/eclair/peers.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; @@ -42,7 +42,7 @@ export const getPeers = (req, res, next) => { }); } else { logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Peers', msg: 'Empty Peers Received' }); - res.status(200).json([]); + return res.status(200).json([]); } }). catch((errRes) => { @@ -91,7 +91,7 @@ export const connectPeer = (req, res, next) => { res.status(201).json(peers); }); } else { - res.status(201).json([]); + return res.status(201).json([]); } }).catch((errRes) => { const err = common.handleError(errRes, 'Peers', 'Connect Peer Error', req.session.selectedNode); diff --git a/server/controllers/lnd/balance.ts b/server/controllers/lnd/balance.ts index fde5efa8..0cc6a3d6 100644 --- a/server/controllers/lnd/balance.ts +++ b/server/controllers/lnd/balance.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/channels.ts b/server/controllers/lnd/channels.ts index 4ccb083d..6c50ab9a 100644 --- a/server/controllers/lnd/channels.ts +++ b/server/controllers/lnd/channels.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/lnd/channelsBackup.ts b/server/controllers/lnd/channelsBackup.ts index 85c4f13f..80974f65 100644 --- a/server/controllers/lnd/channelsBackup.ts +++ b/server/controllers/lnd/channelsBackup.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import { sep } from 'path'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/fees.ts b/server/controllers/lnd/fees.ts index 428b1a41..d722a659 100644 --- a/server/controllers/lnd/fees.ts +++ b/server/controllers/lnd/fees.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { getAllForwardingEvents } from './switch.js'; diff --git a/server/controllers/lnd/getInfo.ts b/server/controllers/lnd/getInfo.ts index 658975ef..f4d09154 100644 --- a/server/controllers/lnd/getInfo.ts +++ b/server/controllers/lnd/getInfo.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { LNDWSClient, LNDWebSocketClient } from './webSocketClient.js'; diff --git a/server/controllers/lnd/graph.ts b/server/controllers/lnd/graph.ts index 6f5ff67b..bfd29fa5 100644 --- a/server/controllers/lnd/graph.ts +++ b/server/controllers/lnd/graph.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/lnd/invoices.ts b/server/controllers/lnd/invoices.ts index 65702ffa..3979bcd0 100644 --- a/server/controllers/lnd/invoices.ts +++ b/server/controllers/lnd/invoices.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { LNDWSClient, LNDWebSocketClient } from './webSocketClient.js'; diff --git a/server/controllers/lnd/message.ts b/server/controllers/lnd/message.ts index 864dddd4..f86d81b7 100644 --- a/server/controllers/lnd/message.ts +++ b/server/controllers/lnd/message.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/newAddress.ts b/server/controllers/lnd/newAddress.ts index cbeb6fc8..ecd1a261 100644 --- a/server/controllers/lnd/newAddress.ts +++ b/server/controllers/lnd/newAddress.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/payments.ts b/server/controllers/lnd/payments.ts index 211a91f7..c736f7c3 100644 --- a/server/controllers/lnd/payments.ts +++ b/server/controllers/lnd/payments.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/lnd/peers.ts b/server/controllers/lnd/peers.ts index a9f6e9ca..3f460b65 100644 --- a/server/controllers/lnd/peers.ts +++ b/server/controllers/lnd/peers.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; import { SelectedNode } from '../../models/config.model.js'; diff --git a/server/controllers/lnd/switch.ts b/server/controllers/lnd/switch.ts index be755263..5c00044a 100644 --- a/server/controllers/lnd/switch.ts +++ b/server/controllers/lnd/switch.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/transactions.ts b/server/controllers/lnd/transactions.ts index 7a47e369..e77e9ee7 100644 --- a/server/controllers/lnd/transactions.ts +++ b/server/controllers/lnd/transactions.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/wallet.ts b/server/controllers/lnd/wallet.ts index b585bf83..0b4afbd2 100644 --- a/server/controllers/lnd/wallet.ts +++ b/server/controllers/lnd/wallet.ts @@ -1,5 +1,5 @@ import atob from 'atob'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/lnd/webSocketClient.ts b/server/controllers/lnd/webSocketClient.ts index 09605704..c4434d3e 100644 --- a/server/controllers/lnd/webSocketClient.ts +++ b/server/controllers/lnd/webSocketClient.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import * as fs from 'fs'; import { join } from 'path'; diff --git a/server/controllers/shared/RTLConf.ts b/server/controllers/shared/RTLConf.ts index f698db4f..ab51798d 100644 --- a/server/controllers/shared/RTLConf.ts +++ b/server/controllers/shared/RTLConf.ts @@ -3,7 +3,7 @@ import * as fs from 'fs'; import { sep } from 'path'; import ini from 'ini'; import parseHocon from 'hocon-parser'; -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Database, DatabaseService } from '../../utils/database.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; diff --git a/server/controllers/shared/boltz.ts b/server/controllers/shared/boltz.ts index 90da9d6e..ec11267a 100644 --- a/server/controllers/shared/boltz.ts +++ b/server/controllers/shared/boltz.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/controllers/shared/loop.ts b/server/controllers/shared/loop.ts index b86a81bd..ede3b14d 100644 --- a/server/controllers/shared/loop.ts +++ b/server/controllers/shared/loop.ts @@ -1,4 +1,4 @@ -import request from 'request-promise'; +import request from '../../utils/request.js'; import { Logger, LoggerService } from '../../utils/logger.js'; import { Common, CommonService } from '../../utils/common.js'; let options = null; diff --git a/server/utils/common.ts b/server/utils/common.ts index d1572737..0314ed7a 100644 --- a/server/utils/common.ts +++ b/server/utils/common.ts @@ -2,7 +2,7 @@ import * as fs from 'fs'; import { join, dirname, isAbsolute, resolve, sep } from 'path'; import { fileURLToPath } from 'url'; import * as crypto from 'crypto'; -import request from 'request-promise'; +import request from './request.js'; import { Logger, LoggerService } from './logger.js'; import { ApplicationConfig, SelectedNode } from '../models/config.model.js'; diff --git a/server/utils/request.ts b/server/utils/request.ts new file mode 100644 index 00000000..fc0ea892 --- /dev/null +++ b/server/utils/request.ts @@ -0,0 +1,77 @@ +import axios from 'axios'; +import * as https from 'https'; + +// Drop-in replacement for the deprecated request-promise, backed by axios. +// Accepts the same options shape used across the controllers ({ url, baseUrl, +// uri, qs, form, body, headers, rejectUnauthorized, json }), resolves with the +// response body directly and rejects with a plain, serializable object that +// mirrors request-promise's StatusCodeError/RequestError shape expected by +// CommonService.handleError. Auth headers are intentionally excluded from the +// rejected error so they can never leak into logs or API error responses. + +const insecureAgent = new https.Agent({ rejectUnauthorized: false }); + +const buildConfig = (options, method: string) => { + const config: any = { + url: options.url && options.url !== '' ? options.url : options.uri, + method: method || options.method || 'GET', + headers: options.headers ? { ...options.headers } : {} + }; + if (options.baseUrl) { config.baseURL = options.baseUrl; } + if (options.qs && Object.keys(options.qs).length > 0) { config.params = options.qs; } + if (options.rejectUnauthorized === false) { config.httpsAgent = insecureAgent; } + if (options.form !== null && options.form !== undefined) { + if (typeof options.form === 'string') { + // Pre-encoded (or raw JSON string for LND's wallet endpoints), send as-is. + config.data = options.form; + } else { + const params = new URLSearchParams(); + Object.entries(options.form).forEach(([key, value]) => { + if (value !== null && value !== undefined) { params.append(key, String(value)); } + }); + config.data = params; + } + config.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } else if (options.body !== null && options.body !== undefined) { + config.data = options.body; + } + if (options.json !== true) { + // Callers without json: true (block explorer, currency rates) JSON.parse the body themselves. + config.responseType = 'text'; + config.transformResponse = [(data) => data]; + } + return config; +}; + +const toRequestPromiseError = (err, config) => { + const errOptions = { url: config.url, method: config.method }; + if (err.response) { + return { + name: 'StatusCodeError', + statusCode: err.response.status, + message: err.response.status + ' - ' + JSON.stringify(err.response.data), + error: err.response.data, + options: errOptions + }; + } + const message = err.message && err.message !== '' ? err.message : err.code; + return { + name: 'RequestError', + message: message, + error: { code: err.code, message: message }, + options: errOptions + }; +}; + +const call = (options, method?: string) => { + const config = buildConfig(options, method); + return axios.request(config).then((response) => response.data).catch((err) => Promise.reject(toRequestPromiseError(err, config))); +}; + +const request = (options) => call(options); +request.get = (options) => call(options, 'GET'); +request.post = (options) => call(options, 'POST'); +request.put = (options) => call(options, 'PUT'); +request.delete = (options) => call(options, 'DELETE'); + +export default request;