From 23ded696bcfb30a1e36c87349a55162040e04e30 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 23 Nov 2021 08:50:27 -1000 Subject: [PATCH 1/4] fetch - dont override server returned error code and message --- src/fetch.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 09ccb80d..511a000d 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -1,5 +1,5 @@ -import { createAsyncMiddleware, JsonRpcMiddleware } from 'json-rpc-engine'; -import { EthereumRpcError, ethErrors } from 'eth-rpc-errors'; +import { createAsyncMiddleware, JsonRpcMiddleware, JsonRpcRequest } from 'json-rpc-engine'; +import { EthereumRpcError, ethErrors, getMessageFromCode } from 'eth-rpc-errors'; import { Payload, Block } from './utils/cache'; /* eslint-disable node/global-require,@typescript-eslint/no-require-imports */ @@ -68,7 +68,7 @@ export function createFetchMiddleware({ `FetchMiddleware - failed to parse response body: "${rawBody}"`, ); } - const result: Block = parseResponse(fetchRes, fetchBody); + const result: Block = parseResponse(fetchRes, fetchBody, req); // set result and exit retry loop res.result = result; return; @@ -106,7 +106,7 @@ function checkForHttpErrors(fetchRes: Response): void { } } -function parseResponse(fetchRes: Response, body: Record): Block { +function parseResponse(fetchRes: Response, body: Record, req: JsonRpcRequest): Block { // check for error code if (fetchRes.status !== 200) { throw ethErrors.rpc.internal({ @@ -117,9 +117,18 @@ function parseResponse(fetchRes: Response, body: Record): Block { // check for rpc error if (body.error) { - throw ethErrors.rpc.internal({ - data: body.error, - }); + const reqData = { req, res: body } + if (body.error.code) { + throw new EthereumRpcError( + body.error.code, + body.error.message || getMessageFromCode(body.error.code), + reqData + ); + } else { + throw ethErrors.rpc.internal({ + data: reqData, + }); + } } // return successful result return body.result; From 2168a1c43f3ebdd20cd5c1645b5e0a6fcba0d71b Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 23 Nov 2021 09:16:58 -1000 Subject: [PATCH 2/4] is this type safety --- src/fetch.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index 511a000d..d12332c6 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -120,8 +120,8 @@ function parseResponse(fetchRes: Response, body: Record, req: Jso const reqData = { req, res: body } if (body.error.code) { throw new EthereumRpcError( - body.error.code, - body.error.message || getMessageFromCode(body.error.code), + Number(body.error.code), + String(body.error.message) || getMessageFromCode(Number(body.error.code)), reqData ); } else { From 52732ae69a31f458f36f4fd2df0252c19645ad9a Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 23 Nov 2021 09:19:19 -1000 Subject: [PATCH 3/4] lint fix --- src/fetch.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index d12332c6..d700828c 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -1,5 +1,13 @@ -import { createAsyncMiddleware, JsonRpcMiddleware, JsonRpcRequest } from 'json-rpc-engine'; -import { EthereumRpcError, ethErrors, getMessageFromCode } from 'eth-rpc-errors'; +import { + createAsyncMiddleware, + JsonRpcMiddleware, + JsonRpcRequest, +} from 'json-rpc-engine'; +import { + EthereumRpcError, + ethErrors, + getMessageFromCode, +} from 'eth-rpc-errors'; import { Payload, Block } from './utils/cache'; /* eslint-disable node/global-require,@typescript-eslint/no-require-imports */ @@ -106,7 +114,11 @@ function checkForHttpErrors(fetchRes: Response): void { } } -function parseResponse(fetchRes: Response, body: Record, req: JsonRpcRequest): Block { +function parseResponse( + fetchRes: Response, + body: Record, + req: JsonRpcRequest, +): Block { // check for error code if (fetchRes.status !== 200) { throw ethErrors.rpc.internal({ @@ -117,12 +129,13 @@ function parseResponse(fetchRes: Response, body: Record, req: Jso // check for rpc error if (body.error) { - const reqData = { req, res: body } + const reqData = { req, res: body }; if (body.error.code) { throw new EthereumRpcError( Number(body.error.code), - String(body.error.message) || getMessageFromCode(Number(body.error.code)), - reqData + String(body.error.message) || + getMessageFromCode(Number(body.error.code)), + reqData, ); } else { throw ethErrors.rpc.internal({ From 46eb9f058c357a4bf7f517a3a9ed0ed454640d38 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 23 Nov 2021 12:43:47 -1000 Subject: [PATCH 4/4] wip --- src/fetch.ts | 2 + test/fetch.js | 194 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 137 insertions(+), 59 deletions(-) diff --git a/src/fetch.ts b/src/fetch.ts index d700828c..28127532 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -129,6 +129,7 @@ function parseResponse( // check for rpc error if (body.error) { + console.log('body.error', body.error) const reqData = { req, res: body }; if (body.error.code) { throw new EthereumRpcError( @@ -138,6 +139,7 @@ function parseResponse( reqData, ); } else { + throw new Error('yabdab') throw ethErrors.rpc.internal({ data: reqData, }); diff --git a/test/fetch.js b/test/fetch.js index b07272cb..72f6aa82 100644 --- a/test/fetch.js +++ b/test/fetch.js @@ -81,65 +81,141 @@ test('fetch - auth in url', (t) => { t.end(); }); -test('fetch - server test', (t) => { - const rpcUrl = 'http://localhost:3000/abc/xyz'; - - const req = { - method: 'eth_getBalance', - params: ['0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 'latest'], - }; +serverTest('fetch - server test', { + createReq() { + return { + id: 1, + json_rpc: '2.0', + method: 'eth_getBalance', + params: ['0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 'latest'], + }; + }, + handleReq() { + return { + id: 1, + result: 42, + }; + }, + afternFn(t, res) { + t.deepEquals(res, { + id: 1, + result: 42, + }); + }, +}); - const rpcRes = { id: 1 }; - let server; - let serverSideRequest; - let serverSidePayload; - - series([createServer, makeRequest, closeServer], (err) => { - t.ifError(err, 'should not error'); - // validate request - t.equals(serverSideRequest.headers.accept, 'application/json'); - t.equals(serverSideRequest.headers['content-type'], 'application/json'); - t.equals(serverSideRequest.method, 'POST'); - // eslint-disable-next-line node/no-deprecated-api - t.equals(serverSideRequest.url, url.parse(rpcUrl).path); - t.deepEquals(serverSidePayload, req); - // validate response - t.deepEquals(rpcRes, { id: 1, result: 42 }); - t.end(); - }); +serverTest('fetch - server with error code', { + createReq() { + return { + id: 1, + json_rpc: '2.0', + method: 'eth_getBalance', + params: ['0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 'latest'], + }; + }, + handleReq() { + return { + id: 1, + error: { + code: 42, + message: 'dank', + }, + }; + }, + afternFn(t, res) { + t.deepEquals(res, { + id: 1, + error: { + code: 42, + message: 'dank', + }, + }); + }, +}); - function requestHandler(request, response) { - request.pipe( - concat((rawRequestBody) => { - const payload = JSON.parse(rawRequestBody.toString()); - // save request details - serverSideRequest = request; - serverSidePayload = payload; - // send response - const responseBody = JSON.stringify({ - id: 1, - result: 42, - }); - response.end(responseBody); - }), - ); - } - - function createServer(cb) { - server = http.createServer(requestHandler); - server.listen(3000, cb); - } - - function closeServer(cb) { - server.close(cb); - } - - function makeRequest(cb) { - const middleware = createFetchMiddleware({ rpcUrl }); - middleware(req, rpcRes, failTest, cb); - } - - function failTest() { - t.fail('something broke'); - } +serverTest('fetch - server with NO error code', { + createReq() { + return { + id: 1, + json_rpc: '2.0', + method: 'eth_getBalance', + params: ['0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2', 'latest'], + }; + }, + handleReq() { + return { + id: 1, + error: { + message: 'big baloo', + }, + }; + }, + afternFn(t, res) { + t.deepEquals(res, { + id: 1, + error: { + message: 'big baloo', + }, + }); + }, }); + +function serverTest(label, { createReq, handleReq, afternFn }) { + test(label, (t) => { + const rpcUrl = 'http://localhost:3000/abc/xyz'; + const clientReq = createReq(); + const clientRes = { id: clientReq.id }; + + let server; + let serverSideNetworkRequest; + let serverSideReq; + let serverSideRes; + + series([createServer, makeRequest, closeServer], (err) => { + t.ifError(err, 'should not error'); + // validate request + t.equals(serverSideNetworkRequest.headers.accept, 'application/json'); + t.equals( + serverSideNetworkRequest.headers['content-type'], + 'application/json', + ); + t.equals(serverSideNetworkRequest.method, 'POST'); + // eslint-disable-next-line node/no-deprecated-api + t.equals(serverSideNetworkRequest.url, url.parse(rpcUrl).path); + afternFn(t, serverSideRes); + t.end(); + }); + + function requestHandler(request, response) { + request.pipe( + concat((rawRequestBody) => { + // save request details + serverSideNetworkRequest = request; + serverSideReq = JSON.parse(rawRequestBody.toString()); + serverSideRes = handleReq(serverSideReq); + // send response + const responseBody = JSON.stringify(serverSideRes); + response.end(responseBody); + }), + ); + } + + function createServer(cb) { + server = http.createServer(requestHandler); + server.listen(3000, cb); + } + + function closeServer(cb) { + server.close(cb); + } + + function makeRequest(cb) { + const middleware = createFetchMiddleware({ rpcUrl }); + middleware(clientReq, clientRes, failTest, (err) => cb()); + } + + function failTest() { + t.fail('something broke'); + } + }); +}