diff --git a/README.md b/README.md index 7a1b4eb..35f151e 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,17 @@ Following the same setup as snyk CLI, it uses the token stored in your system af \ Same thing if you need to designate a different API base url to your onprem instance via `snyk config set endpoint` or `SNYK_API` to `https://yourhostname/api` +>Make sure to omit the base endpoint url when you define url to hit. + ### 1 - Construct your manager - const requestManager = new requestsManager(20, period = 100, maxRetryCount = 10) + + const requestManager = new requestsManager() Default values if using `new requestsManager()`\ - `requestsManager(burstSize = 10, period = 500, maxRetryCount = 5)` + `snykToken = '', burstSize = 10, period = 500, maxRetryCount = 5` + + ### 2 - Single shot request Fire off your request and await it's result. @@ -136,4 +141,23 @@ If not defining custom channel name, default channel name is used in the backend } -Above will only show result of call to `/` as listener is only for 'test-channel' \ No newline at end of file +Above will only show result of call to `/` as listener is only for 'test-channel' + + +### Customize token and or snyk token +While instantiating your manager + +#### Customize queue size and intervals +``` +const requestManager = new requestsManager({burstSize: 20, period: 100, maxRetryCount: 10}) +``` + +#### Customize snyk token +``` +const requestManager = new requestsManager({snykToken:'21346-1234-1234-1234') +``` + +#### Customize snyk token and queue|intervals|retries +``` +const requestManager = new requestsManager({snykToken:'21346-1234-1234-1234', burstSize: 20, period: 100, maxRetryCount: 10}) +``` \ No newline at end of file diff --git a/src/lib/request/request.ts b/src/lib/request/request.ts index 4db012c..1c52d5f 100644 --- a/src/lib/request/request.ts +++ b/src/lib/request/request.ts @@ -10,14 +10,15 @@ interface snykRequest { requestId?: string } -const makeSnykRequest = async (request: snykRequest) => { +const makeSnykRequest = async (request: snykRequest, snykToken: string = '') => { const userConfig = getConfig() + const token = snykToken == '' ? userConfig.token : snykToken + const requestHeaders: Object = { 'Content-Type': 'application/json', - 'Authorization': 'token '+userConfig.token, + 'Authorization': 'token '+ token, 'User-Agent': 'tech-services/snyk-prevent/1.0' - } - + } const apiClient = axios.create({ baseURL: userConfig.endpoint, responseType: 'json', diff --git a/src/lib/request/requestManager.ts b/src/lib/request/requestManager.ts index 820f268..395cc08 100644 --- a/src/lib/request/requestManager.ts +++ b/src/lib/request/requestManager.ts @@ -23,6 +23,12 @@ interface responseEvent { data: any } +interface requestsManagerParams { + snykToken?: string, + burstSize?: number, + period?: number, + maxRetryCount?: number +} class requestsManager { _requestsQueue: LeakyBucketQueue @@ -30,13 +36,16 @@ class requestsManager { _events: any _retryCounter: Map _MAX_RETRY_COUNT: number + _snykToken: string - constructor(burstSize = 10, period = 500, maxRetryCount = 5) { - this._requestsQueue = new LeakyBucketQueue({ burstSize: burstSize, period: period }); + //snykToken = '', burstSize = 10, period = 500, maxRetryCount = 5 + constructor(params: requestsManagerParams = {}) { + this._requestsQueue = new LeakyBucketQueue({ burstSize: params?.burstSize || 10, period: params?.period || 500 }); this._setupQueueExecutors(this._requestsQueue) this._events = {} this._retryCounter = new Map() - this._MAX_RETRY_COUNT = maxRetryCount + this._MAX_RETRY_COUNT = params?.maxRetryCount || 5 + this._snykToken = params?.snykToken || '' } _setupQueueExecutors = (queue: LeakyBucketQueue) => { @@ -52,7 +61,7 @@ class requestsManager { _makeRequest = async (request: queuedRequest) => { let requestId = request.id try { - let response = await makeSnykRequest(request.snykRequest) + let response = await makeSnykRequest(request.snykRequest, this._snykToken) this._emit({eventType: eventType.data, channel: request.channel, requestId: requestId, data: response }) } catch (err) { let overloadedError = requestsManagerError.requestsManagerErrorOverload(err, request.channel, requestId) diff --git a/test/lib/request/request.test.ts b/test/lib/request/request.test.ts index a804ccb..7cded09 100644 --- a/test/lib/request/request.test.ts +++ b/test/lib/request/request.test.ts @@ -13,8 +13,13 @@ import { const fixturesFolderPath = path.resolve(__dirname, '../..') + '/fixtures/'; beforeEach(() => { return nock('https://snyk.io') + .persist() .get(/\/xyz/) .reply(404, '404') + .get(/\/customtoken/) + .reply(200, function() { + return this.req.headers.authorization; + }) .post(/\/xyz/) .reply(404, '404') .get(/\/apierror/) @@ -192,3 +197,23 @@ describe('Test getConfig function', () => { expect(getConfig().endpoint).toEqual('API'); }); }); + +describe('Test snykToken override', () => { + it('Test GET command on / with token override', async () => { + process.env.SNYK_TOKEN = '123'; + const response = await makeSnykRequest( + { verb: 'GET', url: '/customtoken' }, + '0987654321', + ); + expect(_.isEqual(response.data, 'token 0987654321')).toBeTruthy(); + }); + + it('Test GET command on / without token override', async () => { + process.env.SNYK_TOKEN = '123'; + const response = await makeSnykRequest({ + verb: 'GET', + url: '/customtoken', + }); + expect(_.isEqual(response.data, 'token 123')).toBeTruthy(); + }); +}); diff --git a/test/lib/requestManager/normal-flows.test.ts b/test/lib/requestManager/normal-flows.test.ts index be99582..f5a3b62 100644 --- a/test/lib/requestManager/normal-flows.test.ts +++ b/test/lib/requestManager/normal-flows.test.ts @@ -9,6 +9,10 @@ const fixturesFolderPath = path.resolve(__dirname, '../..') + '/fixtures/'; beforeAll(() => { return nock('https://snyk.io') .persist() + .get(/\/customtoken/) + .reply(200, function() { + return this.req.headers.authorization; + }) .get(/\/xyz/) .reply(404, '404') .post(/\/xyz/) @@ -54,9 +58,19 @@ beforeAll(() => { }); }); -const requestManager = new requestsManager(); +const OLD_ENV = process.env; +beforeEach(() => { + jest.resetModules(); // this is important - it clears the cache + process.env = { ...OLD_ENV }; + delete process.env.SNYK_TOKEN; +}); + +afterEach(() => { + process.env = OLD_ENV; +}); describe('Testing Request Flows', () => { + const requestManager = new requestsManager(); it('Single Sync request', async () => { try { const responseSync = await requestManager.request({ @@ -111,7 +125,7 @@ describe('Testing Request Flows', () => { try { // dummypath is slowed down 1sec to verify that the response array respect the order of request // waits for all request to be done and return an array of response in the same order. - const results: any = await requestManager.requestBulk([ + const results: Array = await requestManager.requestBulk([ { verb: 'GET', url: '/dummypath' }, { verb: 'POST', @@ -244,78 +258,33 @@ describe('Testing Request Flows', () => { console.log(err); } }); -}); - -// const run = async () => { -// const manager = new requestsManager() -// manager.on('data', { -// callback:(requestId, data) => { -// console.log("response for request ", requestId) -// console.log(data) -// } -// }) - -// manager.on('error', { -// callback:(requestId, data) => { -// console.log("response for request ", requestId) -// console.log(data) -// } -// }) -// try{ -// let requestSync = await manager.request({verb: "GET", url: '/', body: ''}) -// console.log(requestSync) -// console.log('done with synced request') -// } catch (err) { -// console.log('error') -// console.log(err) -// } - -// manager.on('data', { -// callback:(requestId, data) => { -// console.log("response for request on test-channel ", requestId) -// console.log(data) -// }, -// channel: 'test-channel' -// }) - -// try { -// console.log('1',manager.requestStream({verb: "GET", url: '/', body: ''})) -// console.log('1-channel',manager.requestStream({verb: "GET", url: '/', body: ''}, 'test-channel')) -// console.log('2',manager.requestStream({verb: "GET", url: '/', body: ''})) -// console.log('2-channel',manager.requestStream({verb: "GET", url: '/', body: ''}, 'test-channel')) -// console.log('3',manager.requestStream({verb: "GET", url: '/', body: ''})) -// console.log('3-channel',manager.requestStream({verb: "GET", url: '/', body: ''}, 'test-channel')) -// } catch (err) { -// console.log(err) -// } + it('Single Sync request with no token override', async () => { + process.env.SNYK_TOKEN = '123'; + try { + const responseSync = await requestManager.request({ + verb: 'GET', + url: '/customtoken', + }); + expect(responseSync.data).toEqual('token 123'); + } catch (err) { + throw new Error(err); + } + }); +}); -// const filters = `{ -// "filters": { -// "severities": [ -// "high", -// "medium", -// "low" -// ], -// "exploitMaturity": [ -// "mature", -// "proof-of-concept", -// "no-known-exploit", -// "no-data" -// ], -// "types": [ -// "vuln", -// "license" -// ], -// "ignored": false -// } -// } -// ` -// try { -// const results = await manager.requestBulk([{verb: "GET", url: '/', body: ''}, {verb: "POST", url: '/org/334e0c45-5d3d-40f6-b882-ae82a164b317/project/0bbbfee1-2138-4322-80d4-4166d1259ae5/issues', body: filters}, {verb: "GET", url: '/', body: ''}]) -// console.log(results) -// } catch(resultsWithError) { -// console.log(resultsWithError) -// } +describe('Testing Request Flows', () => { + const requestManager = new requestsManager({ snykToken: '0987654321' }); + it('Single Sync request with token override', async () => { + try { + const responseSync = await requestManager.request({ + verb: 'GET', + url: '/customtoken', + }); -// } + expect(responseSync.data).toEqual('token 0987654321'); + } catch (err) { + throw new Error(err); + } + }); +}); diff --git a/test/lib/requestManager/rate-limits.test.ts b/test/lib/requestManager/rate-limits.test.ts index 339b86f..05300f8 100644 --- a/test/lib/requestManager/rate-limits.test.ts +++ b/test/lib/requestManager/rate-limits.test.ts @@ -55,7 +55,7 @@ beforeAll(() => { describe('Testing Request Rate limiting', () => { describe('Testing Sync requests', () => { it('Overall rate limiting in sync requests - burst size 1', async () => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const t0 = Date.now(); await requestManager.request({ verb: 'GET', url: '/' }); @@ -72,7 +72,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 1 - with slow request', async () => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const t0 = Date.now(); await requestManager.request({ verb: 'GET', url: '/' }); @@ -89,7 +89,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 2', async () => { - const requestManager = new requestsManager(2, 200); + const requestManager = new requestsManager({ burstSize: 2, period: 200 }); const t0 = Date.now(); await requestManager.request({ verb: 'GET', url: '/' }); @@ -106,7 +106,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 4', async () => { - const requestManager = new requestsManager(4, 200); + const requestManager = new requestsManager({ burstSize: 4, period: 200 }); const t0 = Date.now(); await requestManager.request({ verb: 'GET', url: '/' }); @@ -123,9 +123,8 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in bulk sync requests - burst size 1', async () => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const t0 = Date.now(); - await requestManager.requestBulk([ { verb: 'GET', url: '/' }, { verb: 'GET', url: '/' }, @@ -142,7 +141,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in bulk sync requests - burst size 1 with slow request', async () => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const t0 = Date.now(); await requestManager.requestBulk([ @@ -161,7 +160,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in bulk sync requests - burst size 2', async () => { - const requestManager = new requestsManager(2, 200); + const requestManager = new requestsManager({ burstSize: 2, period: 200 }); const t0 = Date.now(); await requestManager.requestBulk([ @@ -180,7 +179,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in bulk sync requests - burst size 4', async () => { - const requestManager = new requestsManager(4, 200); + const requestManager = new requestsManager({ burstSize: 4, period: 200 }); const t0 = Date.now(); await requestManager.requestBulk([ @@ -201,7 +200,7 @@ describe('Testing Request Rate limiting', () => { describe('Testing Stream requests', () => { it('Overall rate limiting in sync requests - burst size 1', async (done) => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -263,7 +262,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 1 with slow request', async (done) => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -322,7 +321,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 2', async (done) => { - const requestManager = new requestsManager(2, 200); + const requestManager = new requestsManager({ burstSize: 2, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -384,7 +383,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in sync requests - burst size 4', async (done) => { - const requestManager = new requestsManager(4, 200); + const requestManager = new requestsManager({ burstSize: 4, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -448,7 +447,7 @@ describe('Testing Request Rate limiting', () => { describe('Testing Stream + Sync requests', () => { it('Overall rate limiting in mixed (sync+stream) requests - burst size 1', async (done) => { - const requestManager = new requestsManager(1, 200); + const requestManager = new requestsManager({ burstSize: 1, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -520,7 +519,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in mixed (sync+stream) requests - burst size 2', async (done) => { - const requestManager = new requestsManager(2, 200); + const requestManager = new requestsManager({ burstSize: 2, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -592,7 +591,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in mixed (sync+stream) requests - burst size 4', async (done) => { - const requestManager = new requestsManager(4, 200); + const requestManager = new requestsManager({ burstSize: 4, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now(); @@ -664,7 +663,7 @@ describe('Testing Request Rate limiting', () => { }); it('Overall rate limiting in mixed (sync+bulk+stream) requests - burst size 4', async (done) => { - const requestManager = new requestsManager(4, 200); + const requestManager = new requestsManager({ burstSize: 4, period: 200 }); const responseIdArray: Array = []; const t0 = Date.now();