From 5650afb22fb0766da1096553c1ab817fef55e119 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 08:40:48 -0800 Subject: [PATCH 01/10] fix(decodeError): Adding additional error handling --- src/routes/v4/route-utils.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js index cab689c..9ef99d3 100644 --- a/src/routes/v4/route-utils.js +++ b/src/routes/v4/route-utils.js @@ -175,6 +175,20 @@ function decodeError (err) { } } + // Handle 429 errors thrown by nginx + if (err.error) { + if (err.error.includes('429 Too Many Requests')) { + const internalMsg = '429 error thrown by nginx caught by route-utils.js/decodeError()' + console.error(internalMsg) + wlogger.error(internalMsg) + + return { + msg: '429 Too Many Requests', + status: 429 + } + } + } + // Handle general Error objects. if (err.message) { return { From 8de2e9e10b990e290eb8ee94cb06fc8def7cba88 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 08:44:24 -0800 Subject: [PATCH 02/10] debugging --- src/routes/v4/route-utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js index 9ef99d3..c81649a 100644 --- a/src/routes/v4/route-utils.js +++ b/src/routes/v4/route-utils.js @@ -177,6 +177,8 @@ function decodeError (err) { // Handle 429 errors thrown by nginx if (err.error) { + console.log('decodeError: err: ', err) + if (err.error.includes('429 Too Many Requests')) { const internalMsg = '429 error thrown by nginx caught by route-utils.js/decodeError()' console.error(internalMsg) From be6550686f005c4c52f3309ca7a5c672baf36a6e Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 08:46:20 -0800 Subject: [PATCH 03/10] debugging --- src/routes/v4/route-utils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js index c81649a..d0e902d 100644 --- a/src/routes/v4/route-utils.js +++ b/src/routes/v4/route-utils.js @@ -175,6 +175,8 @@ function decodeError (err) { } } + console.log(`JSON of error: ${JSON.stringify(err, null, 2)}`) + // Handle 429 errors thrown by nginx if (err.error) { console.log('decodeError: err: ', err) From ef49b85495b3d703f2b0962807ff569b02eb6214 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 08:48:22 -0800 Subject: [PATCH 04/10] debugging --- src/routes/v4/route-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js index d0e902d..9e8262f 100644 --- a/src/routes/v4/route-utils.js +++ b/src/routes/v4/route-utils.js @@ -118,6 +118,8 @@ function getAxiosOptions () { // If there is a failure, obj.msg is false. function decodeError (err) { try { + console.log(`JSON of error: ${JSON.stringify(err, null, 2)}`) + // Attempt to extract the full node error message. if ( err.response && @@ -175,8 +177,6 @@ function decodeError (err) { } } - console.log(`JSON of error: ${JSON.stringify(err, null, 2)}`) - // Handle 429 errors thrown by nginx if (err.error) { console.log('decodeError: err: ', err) From 3ddbb728b46908bbda3b62470483b1686aed3863 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 08:52:02 -0800 Subject: [PATCH 05/10] debugging --- src/routes/v4/route-utils.js | 1 + src/routes/v4/slp.js | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js index 9e8262f..108def4 100644 --- a/src/routes/v4/route-utils.js +++ b/src/routes/v4/route-utils.js @@ -118,6 +118,7 @@ function getAxiosOptions () { // If there is a failure, obj.msg is false. function decodeError (err) { try { + console.log('ping10') console.log(`JSON of error: ${JSON.stringify(err, null, 2)}`) // Attempt to extract the full node error message. diff --git a/src/routes/v4/slp.js b/src/routes/v4/slp.js index 6beec5c..5e0324c 100644 --- a/src/routes/v4/slp.js +++ b/src/routes/v4/slp.js @@ -104,6 +104,8 @@ class Slp { // DRY error handler. errorHandler (err, res) { + console.error('Entering slp.js/errorHandler(). err: ', err) + // Attempt to decode the error message. const { msg, status } = _this.routeUtils.decodeError(err) if (msg) { @@ -2050,9 +2052,12 @@ class Slp { res.status(200) return res.json({ slpUtxos: utxos }) } catch (err) { + console.log('ping01') wlogger.error('Error in slp.js/hydrateUtxos().', err) console.error('Error in slp.js/hydrateUtxos().', err) + console.log('ping02') + // Decode the error message. const { msg, status } = routeUtils.decodeError(err) console.log('msg: ', msg) @@ -2062,6 +2067,8 @@ class Slp { return res.json({ error: msg, message: msg, success: false }) } + console.log('ping03') + res.status(500) return res.json({ error: 'Undetermined error in hydrateUtxos()', From e37858fd19988df1f342b8d70d457ec3d2613ed3 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Thu, 11 Mar 2021 09:04:26 -0800 Subject: [PATCH 06/10] debugging --- src/routes/v4/slp.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/routes/v4/slp.js b/src/routes/v4/slp.js index 5e0324c..eb360ed 100644 --- a/src/routes/v4/slp.js +++ b/src/routes/v4/slp.js @@ -108,6 +108,9 @@ class Slp { // Attempt to decode the error message. const { msg, status } = _this.routeUtils.decodeError(err) + console.log('slp.js/errorHandler msg from decodeError: ', msg) + console.log('slp.js/errorHandler status from decodeError: ', status) + if (msg) { res.status(status) return res.json({ error: msg }) From 93811ca33109d6eb797cdea76e7cbb5210426215 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 16 Mar 2021 08:43:43 -0700 Subject: [PATCH 07/10] fix(route-utils): Removing old route-utils and using new route-utils --- src/routes/v4/route-utils.js | 211 ----------------------------------- src/routes/v4/util.js | 4 +- src/routes/v4/xpub.js | 6 +- src/util/route-utils.js | 23 ++++ 4 files changed, 30 insertions(+), 214 deletions(-) delete mode 100644 src/routes/v4/route-utils.js diff --git a/src/routes/v4/route-utils.js b/src/routes/v4/route-utils.js deleted file mode 100644 index 108def4..0000000 --- a/src/routes/v4/route-utils.js +++ /dev/null @@ -1,211 +0,0 @@ -/* - A private library of utility functions used by several different routes. -*/ - -'use strict' - -const axios = require('axios') -const wlogger = require('../../util/winston-logging') - -const util = require('util') -util.inspect.defaultOptions = { depth: 1 } - -const BCHJS = require('@psf/bch-js') -const bchjs = new BCHJS() - -module.exports = { - validateNetwork, // Prevents a common user error - setEnvVars, // Allows RPC variables to be set dynamically based on changing env vars. - decodeError, // Extract and interpret error messages. - validateArraySize, // Ensure the passed array meets rate limiting requirements. - getAxiosOptions -} - -// This function expects the Request Express.js object and an array as input. -// The array is then validated against freemium and pro-tier rate limiting -// requirements. A boolean is returned to indicate if the array size if valid -// or not. -function validateArraySize (req, array) { - const FREEMIUM_INPUT_SIZE = 20 - const PRO_INPUT_SIZE = 20 - - if (req.locals && req.locals.proLimit) { - if (array.length <= PRO_INPUT_SIZE) return true - } else if (array.length <= FREEMIUM_INPUT_SIZE) { - return true - } - - return false -} - -// Returns true if user-provided cash address matches the correct network, -// mainnet or testnet. If NETWORK env var is not defined, it returns false. -// This prevent a common user-error issue that is easy to make: passing a -// testnet address into rest.bitcoin.com or passing a mainnet address into -// trest.bitcoin.com. -function validateNetwork (addr) { - try { - const network = process.env.NETWORK - - // Return false if NETWORK is not defined. - if (!network || network === '') { - console.log('Warning: NETWORK environment variable is not defined!') - return false - } - - // Convert the user-provided address to a cashaddress, for easy detection - // of the intended network. - const cashAddr = bchjs.Address.toCashAddress(addr) - - // Return true if the network and address both match testnet - const addrIsTest = bchjs.Address.isTestnetAddress(cashAddr) - if (network === 'testnet' && addrIsTest) return true - - // Return true if the network and address both match mainnet - const addrIsMain = bchjs.Address.isMainnetAddress(cashAddr) - if (network === 'mainnet' && addrIsMain) return true - - return false - } catch (err) { - wlogger.error('Error in validateNetwork()') - return false - } -} - -// Dynamically set these based on env vars. Allows unit testing. -function setEnvVars () { - const BitboxHTTP = axios.create({ - baseURL: process.env.RPC_BASEURL, - timeout: 15000 - }) - const username = process.env.RPC_USERNAME - const password = process.env.RPC_PASSWORD - - const requestConfig = { - method: 'post', - auth: { - username: username, - password: password - }, - data: { - jsonrpc: '1.0' - } - } - - return { BitboxHTTP, username, password, requestConfig } -} - -// Axios options used when calling axios.post() to talk with a full node. -function getAxiosOptions () { - return { - method: 'post', - baseURL: process.env.RPC_BASEURL, - timeout: 15000, - auth: { - username: process.env.RPC_USERNAME, - password: process.env.RPC_PASSWORD - }, - data: { - jsonrpc: '1.0' - } - } -} - -// Error messages returned by a full node can be burried pretty deep inside the -// error object returned by Axios. This function attempts to extract and interpret -// error messages. -// Returns an object. If successful, obj.msg is a string. -// If there is a failure, obj.msg is false. -function decodeError (err) { - try { - console.log('ping10') - console.log(`JSON of error: ${JSON.stringify(err, null, 2)}`) - - // Attempt to extract the full node error message. - if ( - err.response && - err.response.data && - err.response.data.error && - err.response.data.error.message - ) { - return { msg: err.response.data.error.message, status: 400 } - } - - // Attempt to extract the Insight error message - if (err.response && err.response.data) { - return { msg: err.response.data, status: err.response.status } - } - - // console.log(`err.message: ${err.message}`) - // console.log(`err: `, err) - - // Attempt to detect a network connection error. - if (err.message && err.message.indexOf('ENOTFOUND') > -1) { - return { - msg: - 'Network error: Could not communicate with full node or other external service.', - status: 503 - } - } - - // Different kind of network error - if (err.message && err.message.indexOf('ENETUNREACH') > -1) { - return { - msg: - 'Network error: Could not communicate with full node or other external service.', - status: 503 - } - } - - // Different kind of network error - if (err.message && err.message.indexOf('EAI_AGAIN') > -1) { - return { - msg: - 'Network error: Could not communicate with full node or other external service.', - status: 503 - } - } - - // Axios timeout (aborted) error, or service is down (connection refused). - if ( - err.code && - (err.code === 'ECONNABORTED' || err.code === 'ECONNREFUSED') - ) { - return { - msg: - 'Network error: Could not communicate with full node or other external service.', - status: 503 - } - } - - // Handle 429 errors thrown by nginx - if (err.error) { - console.log('decodeError: err: ', err) - - if (err.error.includes('429 Too Many Requests')) { - const internalMsg = '429 error thrown by nginx caught by route-utils.js/decodeError()' - console.error(internalMsg) - wlogger.error(internalMsg) - - return { - msg: '429 Too Many Requests', - status: 429 - } - } - } - - // Handle general Error objects. - if (err.message) { - return { - message: err.message, - status: 422 - } - } - - return { msg: false, status: 500 } - } catch (err) { - console.error('unhandled error in route-utils.js/decodeError(): ', err) - wlogger.error('unhandled error in route-utils.js/decodeError(): ', err) - return { msg: false, status: 500 } - } -} diff --git a/src/routes/v4/util.js b/src/routes/v4/util.js index 7862aad..e3d20a7 100644 --- a/src/routes/v4/util.js +++ b/src/routes/v4/util.js @@ -4,7 +4,9 @@ const express = require('express') const router = express.Router() const axios = require('axios') -const routeUtils = require('./route-utils') +const RouteUtils = require('../../util/route-utils') +const routeUtils = new RouteUtils() + const wlogger = require('../../util/winston-logging') const util = require('util') diff --git a/src/routes/v4/xpub.js b/src/routes/v4/xpub.js index fa1d9d4..e3410c9 100644 --- a/src/routes/v4/xpub.js +++ b/src/routes/v4/xpub.js @@ -5,8 +5,10 @@ 'use strict' const express = require('express') -// const axios = require('axios') -const routeUtils = require('./route-utils') + +const RouteUtils = require('../../util/route-utils') +const routeUtils = new RouteUtils() + const wlogger = require('../../util/winston-logging') // const router = express.Router() diff --git a/src/util/route-utils.js b/src/util/route-utils.js index d5a98ff..49335df 100644 --- a/src/util/route-utils.js +++ b/src/util/route-utils.js @@ -169,6 +169,29 @@ class RouteUtils { return { msg: false, status: 500 } } } + + // Dynamically set these based on env vars. Allows unit testing. + setEnvVars () { + const BitboxHTTP = axios.create({ + baseURL: process.env.RPC_BASEURL, + timeout: 15000 + }) + const username = process.env.RPC_USERNAME + const password = process.env.RPC_PASSWORD + + const requestConfig = { + method: 'post', + auth: { + username: username, + password: password + }, + data: { + jsonrpc: '1.0' + } + } + + return { BitboxHTTP, username, password, requestConfig } + } } module.exports = RouteUtils From 27e5fb872839ce5542a43cfec7f82b3fe6414a50 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 16 Mar 2021 08:48:15 -0700 Subject: [PATCH 08/10] fix(route-utils): Adding handler for nginx 429 error --- src/util/route-utils.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/util/route-utils.js b/src/util/route-utils.js index 49335df..ba32ca1 100644 --- a/src/util/route-utils.js +++ b/src/util/route-utils.js @@ -154,6 +154,23 @@ class RouteUtils { } } + // Handle 429 errors thrown by nginx + if (err.error) { + console.log('decodeError: err: ', err) + + if (err.error.includes('429 Too Many Requests')) { + const internalMsg = + '429 error thrown by nginx caught by route-utils.js/decodeError()' + console.error(internalMsg) + wlogger.error(internalMsg) + + return { + msg: '429 Too Many Requests', + status: 429 + } + } + } + // Handle general Error objects. if (err.message) { return { From 62600fdd62b2f2c80ac430a4dcf993ec804d83c4 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 16 Mar 2021 08:56:14 -0700 Subject: [PATCH 09/10] Backing down on some of the debugger statements --- src/routes/v4/slp.js | 12 ++++-------- src/util/route-utils.js | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/routes/v4/slp.js b/src/routes/v4/slp.js index eb360ed..69cce00 100644 --- a/src/routes/v4/slp.js +++ b/src/routes/v4/slp.js @@ -2055,23 +2055,19 @@ class Slp { res.status(200) return res.json({ slpUtxos: utxos }) } catch (err) { - console.log('ping01') wlogger.error('Error in slp.js/hydrateUtxos().', err) - console.error('Error in slp.js/hydrateUtxos().', err) - - console.log('ping02') + // console.error('Error in slp.js/hydrateUtxos().', err) // Decode the error message. const { msg, status } = routeUtils.decodeError(err) - console.log('msg: ', msg) - console.log('status: ', status) + // console.log('msg: ', msg) + // console.log('status: ', status) + if (msg) { res.status(status) return res.json({ error: msg, message: msg, success: false }) } - console.log('ping03') - res.status(500) return res.json({ error: 'Undetermined error in hydrateUtxos()', diff --git a/src/util/route-utils.js b/src/util/route-utils.js index ba32ca1..f297469 100644 --- a/src/util/route-utils.js +++ b/src/util/route-utils.js @@ -156,7 +156,7 @@ class RouteUtils { // Handle 429 errors thrown by nginx if (err.error) { - console.log('decodeError: err: ', err) + // console.log('decodeError: err: ', err) if (err.error.includes('429 Too Many Requests')) { const internalMsg = From 9c735e3c5ab69db3e8cbd23ac02970d916e72b36 Mon Sep 17 00:00:00 2001 From: Chris Troutner Date: Tue, 16 Mar 2021 09:00:47 -0700 Subject: [PATCH 10/10] Removing more debugging statements --- src/routes/v4/slp.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/v4/slp.js b/src/routes/v4/slp.js index 69cce00..1abf58f 100644 --- a/src/routes/v4/slp.js +++ b/src/routes/v4/slp.js @@ -104,7 +104,7 @@ class Slp { // DRY error handler. errorHandler (err, res) { - console.error('Entering slp.js/errorHandler(). err: ', err) + // console.error('Entering slp.js/errorHandler(). err: ', err) // Attempt to decode the error message. const { msg, status } = _this.routeUtils.decodeError(err)