Skip to content

Commit

Permalink
feat(request-node): Add Request Node version and Request Client versi…
Browse files Browse the repository at this point in the history
…on to requests header (#192)
  • Loading branch information
lumtis committed Apr 14, 2020
1 parent 5957961 commit 20ad94b
Show file tree
Hide file tree
Showing 5 changed files with 366 additions and 227 deletions.
10 changes: 10 additions & 0 deletions packages/request-client.js/src/http-data-access.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import axios, { AxiosRequestConfig } from 'axios';

import { EventEmitter } from 'events';

const packageJson = require('../package.json');

const REQUEST_CLIENT_VERSION_HEADER = 'X-Request-Network-Client-Version';

// Maximum number of retries to attempt when http requests to the Node fail
const HTTP_REQUEST_MAX_RETRY = 3;

Expand Down Expand Up @@ -31,9 +35,15 @@ export default class HttpDataAccess implements DataAccessTypes.IDataAccess {
* @param nodeConnectionConfig Configuration options to connect to the node. Follows Axios configuration format.
*/
constructor(nodeConnectionConfig: AxiosRequestConfig = {}) {
// Get Request Client version to set it in the header
const requestClientVersion = packageJson.version;

this.axiosConfig = Object.assign(
{
baseURL: 'http://localhost:3000',
headers: {
[REQUEST_CLIENT_VERSION_HEADER]: requestClientVersion,
},
},
nodeConnectionConfig,
);
Expand Down
37 changes: 36 additions & 1 deletion packages/request-client.js/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import * as TestDataRealBTC from './data-test-real-btc';

import { PaymentReferenceCalculator } from '@requestnetwork/payment-detection';

const packageJson = require('../package.json');
const REQUEST_CLIENT_VERSION_HEADER = 'X-Request-Network-Client-Version';

const chai = require('chai');
const spies = require('chai-spies');
const chaiAsPromised = require('chai-as-promised');
Expand Down Expand Up @@ -144,6 +147,38 @@ describe('index', () => {
sandbox.restore();
});

it('specify the Request Client version in the header', async () => {
const mock = new mockAdapter(axios);

const callback = (config: any): any => {
expect(config.headers[REQUEST_CLIENT_VERSION_HEADER]).to.equal(packageJson.version);
return [200, {}];
};
const spy = chai.spy(callback);
mock.onPost('/persistTransaction').reply(spy);
mock
.onGet('/getTransactionsByChannelId')
.reply(200, { result: { transactions: [TestData.timestampedTransaction] } });
mock.onGet('/getConfirmedTransaction').reply(200, { result: {} });

const requestNetwork = new RequestNetwork({ signatureProvider: fakeSignatureProvider });

requestNetwork.bitcoinDetectionProvider = mockBTCProvider;

const paymentNetwork: PaymentTypes.IPaymentNetworkCreateParameters = {
id: PaymentTypes.PAYMENT_NETWORK_ID.DECLARATIVE,
parameters: {},
};
const request = await requestNetwork.createRequest({
paymentNetwork,
requestInfo: TestData.parametersWithoutExtensionsData,
signer: payeeIdentity,
});
expect(spy).to.have.been.called.once;

await request.waitForConfirmation();
});

it('uses http://localhost:3000 with signatureProvider and paymentNetwork', async () => {
const mock = new mockAdapter(axios);

Expand Down Expand Up @@ -1362,7 +1397,7 @@ describe('index', () => {
});

// This test checks that 2 payments with reference `fb8cc0abeed87cb8` have reached 0xc12F17Da12cd01a9CDBB216949BA0b41A6Ffc4EB
it('can get the balance of an ETH request', async function(): Promise<void> {
it('can get the balance of an ETH request', async function (): Promise<void> {
const clock: sinon.SinonFakeTimers = sinon.useFakeTimers();

// tslint:disable-next-line: no-invalid-this
Expand Down
14 changes: 14 additions & 0 deletions packages/request-node/src/requestNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ import ipfsAdd from './request/ipfsAdd';
import PersistTransaction from './request/persistTransaction';
import { getEthereumStorage } from './storageUtils';

const packageJson = require('../package.json');

const NOT_FOUND_MESSAGE =
'Not found\nAvailable endpoints:\n/POST persistTransaction\n/GET getTransactionsByChannelId\n/GET getChannelsByTopic\n/POST /ipfsAdd\nGET getConfirmedTransaction\nGET status';

const NOT_INITIALIZED_MESSAGE = 'The node is not initialized';

const REQUEST_NODE_VERSION_HEADER = 'X-Request-Network-Node-Version';

/**
* Main class for request node express server
* This class defines routes to handle requests from client
Expand All @@ -38,6 +42,7 @@ class RequestNode {
private logger: LogTypes.ILogger;
private persistTransaction: PersistTransaction;
private confirmedTransactionStore: ConfirmedTransactionStore;
private requestNodeVersion: string;
/**
* Request Node constructor
*
Expand Down Expand Up @@ -74,6 +79,9 @@ class RequestNode {

this.express = express();
this.mountRoutes();

// Get the version of the Request Node for the request's response header
this.requestNodeVersion = packageJson.version;
}

/**
Expand Down Expand Up @@ -142,6 +150,12 @@ class RequestNode {
});
}

// Set the Request Node version to the header
this.express.use((_: any, res: any, next: any) => {
res.header(REQUEST_NODE_VERSION_HEADER, this.requestNodeVersion);
next();
});

// Supported encodings
this.express.use(express.json());
this.express.use(express.urlencoded({ extended: true }));
Expand Down
13 changes: 13 additions & 0 deletions packages/request-node/test/requestNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import requestNode from '../src/requestNode';
chai.use(chaiAsPromised);
const expect = chai.expect;

const packageJson = require('../package.json');
const requestNodeVersion = packageJson.version;

const dataAccessInitializeFailureMock = async (): Promise<never> => {
throw Error('This mock function always fails');
};
Expand Down Expand Up @@ -99,6 +102,16 @@ describe('requestNode server', () => {
.expect('x-custom-test-header', 'test-passed');
});

it('the response header contains the Request Node version', async () => {
// Import directly requestNode to create a server
requestNodeInstance = new requestNode();
server = requestNodeInstance.listen(3003, () => 0);

await request(server)
.post('/')
.expect('X-Request-Network-Node-Version', requestNodeVersion);
});

it('must throw if no mnemonic given with rinkeby', async () => {
process.env.ETHEREUM_NETWORK_ID = '4';

Expand Down
Loading

0 comments on commit 20ad94b

Please sign in to comment.