From 6aad759d79485869d0bfec9cdac73779fa8b2426 Mon Sep 17 00:00:00 2001 From: Jeff Schmidt Date: Mon, 22 Jul 2024 14:59:56 -0600 Subject: [PATCH 1/2] At the request hander middleware level, lowercase order and result parameter values. Introduce small framework to extend to other query parameter keys as required. Signed-off-by: Jeff Schmidt --- .../logs/pagination-index-timestamp-range.json | 10 ++++++++-- .../specs/transactions/all-params.json | 6 +++++- .../middleware/requestHandler.js | 18 ++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/hedera-mirror-rest/__tests__/specs/contracts/results/logs/pagination-index-timestamp-range.json b/hedera-mirror-rest/__tests__/specs/contracts/results/logs/pagination-index-timestamp-range.json index bebda405f34..d49c17b3d24 100644 --- a/hedera-mirror-rest/__tests__/specs/contracts/results/logs/pagination-index-timestamp-range.json +++ b/hedera-mirror-rest/__tests__/specs/contracts/results/logs/pagination-index-timestamp-range.json @@ -206,7 +206,11 @@ } }, { - "url": "/api/v1/contracts/results/logs?timestamp=gte:1639010151.000000000×tamp=lte:1639010161.000000000&limit=3&order=desc&index=lte:1", + "urls": [ + "/api/v1/contracts/results/logs?timestamp=gte:1639010151.000000000×tamp=lte:1639010161.000000000&limit=3&order=desc&index=lte:1", + "/api/v1/contracts/results/logs?timestamp=gte:1639010151.000000000×tamp=lte:1639010161.000000000&limit=3&order=DESC&index=lte:1", + "/api/v1/contracts/results/logs?timestamp=gte:1639010151.000000000×tamp=lte:1639010161.000000000&limit=3&order=DeSc&index=lte:1" + ], "responseStatus": 200, "responseJson": { "logs": [ @@ -324,7 +328,9 @@ }, { "urls": [ - "/api/v1/contracts/results/logs?index=gte:0×tamp=gte:1639010141.000000000&index=lte:1×tamp=lte:1639010141.000000000&limit=1&order=asc" + "/api/v1/contracts/results/logs?index=gte:0×tamp=gte:1639010141.000000000&index=lte:1×tamp=lte:1639010141.000000000&limit=1&order=asc", + "/api/v1/contracts/results/logs?index=gte:0×tamp=gte:1639010141.000000000&index=lte:1×tamp=lte:1639010141.000000000&limit=1&order=ASC", + "/api/v1/contracts/results/logs?index=gte:0×tamp=gte:1639010141.000000000&index=lte:1×tamp=lte:1639010141.000000000&limit=1&order=Asc" ], "responseStatus": 200, "responseJson": { diff --git a/hedera-mirror-rest/__tests__/specs/transactions/all-params.json b/hedera-mirror-rest/__tests__/specs/transactions/all-params.json index a2fbd7133dd..c8b5d9e749a 100644 --- a/hedera-mirror-rest/__tests__/specs/transactions/all-params.json +++ b/hedera-mirror-rest/__tests__/specs/transactions/all-params.json @@ -72,7 +72,11 @@ }, "tests": [ { - "url": "/api/v1/transactions?timestamp=1565779209.711927001&account.id=0.0.9&type=credit&result=success", + "urls": [ + "/api/v1/transactions?timestamp=1565779209.711927001&account.id=0.0.9&type=credit&result=success&order=asc", + "/api/v1/transactions?timestamp=1565779209.711927001&account.id=0.0.9&type=credit&result=SUCCESS&order=ASC", + "/api/v1/transactions?timestamp=1565779209.711927001&account.id=0.0.9&type=credit&result=SucCess&order=AsC" + ], "responseStatus": 200, "responseJson": { "transactions": [ diff --git a/hedera-mirror-rest/middleware/requestHandler.js b/hedera-mirror-rest/middleware/requestHandler.js index 838aafdfac7..a96cafa429a 100644 --- a/hedera-mirror-rest/middleware/requestHandler.js +++ b/hedera-mirror-rest/middleware/requestHandler.js @@ -20,6 +20,18 @@ import qs from 'qs'; import {httpStatusCodes, requestIdLabel, requestStartTime} from '../constants'; import {randomString} from '../utils'; +const lowerCaseQueryValue = (queryValue) => { + if (typeof queryValue === 'string') { + return queryValue.toLowerCase(); + } + return queryValue; +}; + +const queryCanonicalizationMap = { + order: lowerCaseQueryValue, + result: lowerCaseQueryValue, +}; + const requestLogger = async (req, res, next) => { const requestId = await randomString(8); httpContext.set(requestIdLabel, requestId); @@ -57,11 +69,13 @@ const requestQueryParser = (queryString) => { const caseInsensitiveQueryString = {}; for (const [key, value] of Object.entries(parsedQueryString)) { const lowerKey = key.toLowerCase(); + const canonicalizationFunc = queryCanonicalizationMap[lowerKey]; + const canonicalizedValue = canonicalizationFunc ? canonicalizationFunc(value) : value; if (lowerKey in caseInsensitiveQueryString) { // handle repeated values, merge into an array - caseInsensitiveQueryString[lowerKey] = merge(caseInsensitiveQueryString[lowerKey], value); + caseInsensitiveQueryString[lowerKey] = merge(caseInsensitiveQueryString[lowerKey], canonicalizedValue); } else { - caseInsensitiveQueryString[lowerKey] = value; + caseInsensitiveQueryString[lowerKey] = canonicalizedValue; } } From d4e81e19a54fd3222b95ccb089be5bf8528778eb Mon Sep 17 00:00:00 2001 From: Xin Li Date: Tue, 23 Jul 2024 12:35:33 -0500 Subject: [PATCH 2/2] improve test coverage Signed-off-by: Xin Li --- hedera-mirror-rest/__tests__/utils.test.js | 12 ++++++++++++ hedera-mirror-rest/middleware/requestHandler.js | 15 ++++----------- hedera-mirror-rest/utils.js | 3 +++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/hedera-mirror-rest/__tests__/utils.test.js b/hedera-mirror-rest/__tests__/utils.test.js index c535eb4ff7f..ad37730c284 100644 --- a/hedera-mirror-rest/__tests__/utils.test.js +++ b/hedera-mirror-rest/__tests__/utils.test.js @@ -2039,3 +2039,15 @@ describe('bigIntMin', () => { expect(utils.bigIntMin(a, b)).toEqual(expected); }); }); + +describe('lowerCaseQueryValue', () => { + test.each` + input | expected + ${'success'} | ${'success'} + ${'SUCCESS'} | ${'success'} + ${'SUCCess'} | ${'success'} + ${100} | ${100} + `('$input', ({input, expected}) => { + expect(utils.lowerCaseQueryValue(input)).toEqual(expected); + }); +}); diff --git a/hedera-mirror-rest/middleware/requestHandler.js b/hedera-mirror-rest/middleware/requestHandler.js index a96cafa429a..6dfac144518 100644 --- a/hedera-mirror-rest/middleware/requestHandler.js +++ b/hedera-mirror-rest/middleware/requestHandler.js @@ -18,14 +18,7 @@ import httpContext from 'express-http-context'; import qs from 'qs'; import {httpStatusCodes, requestIdLabel, requestStartTime} from '../constants'; -import {randomString} from '../utils'; - -const lowerCaseQueryValue = (queryValue) => { - if (typeof queryValue === 'string') { - return queryValue.toLowerCase(); - } - return queryValue; -}; +import {lowerCaseQueryValue, randomString} from '../utils'; const queryCanonicalizationMap = { order: lowerCaseQueryValue, @@ -70,12 +63,12 @@ const requestQueryParser = (queryString) => { for (const [key, value] of Object.entries(parsedQueryString)) { const lowerKey = key.toLowerCase(); const canonicalizationFunc = queryCanonicalizationMap[lowerKey]; - const canonicalizedValue = canonicalizationFunc ? canonicalizationFunc(value) : value; + const canonicalValue = canonicalizationFunc ? canonicalizationFunc(value) : value; if (lowerKey in caseInsensitiveQueryString) { // handle repeated values, merge into an array - caseInsensitiveQueryString[lowerKey] = merge(caseInsensitiveQueryString[lowerKey], canonicalizedValue); + caseInsensitiveQueryString[lowerKey] = merge(caseInsensitiveQueryString[lowerKey], canonicalValue); } else { - caseInsensitiveQueryString[lowerKey] = canonicalizedValue; + caseInsensitiveQueryString[lowerKey] = canonicalValue; } } diff --git a/hedera-mirror-rest/utils.js b/hedera-mirror-rest/utils.js index c33c1b15197..a13ed66239b 100644 --- a/hedera-mirror-rest/utils.js +++ b/hedera-mirror-rest/utils.js @@ -211,6 +211,8 @@ const isValidAddressBookFileIdPattern = (fileId) => { return addressBookFileIdPattern.includes(fileId); }; +const lowerCaseQueryValue = (queryValue) => (typeof queryValue === 'string' ? queryValue.toLowerCase() : queryValue); + /** * Validate input parameters for the rest apis * @param {String} param Parameter to be validated @@ -1743,6 +1745,7 @@ export { isValidSlot, isValidTimestampParam, isValidValueIgnoreCase, + lowerCaseQueryValue, ltLte, mergeParams, nowInNs,