@autofleet/network 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +26 -0
- package/index.js +95 -0
- package/index.test.js +69 -0
- package/jest.config.js +8 -0
- package/package.json +24 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
jobs:
|
|
3
|
+
test:
|
|
4
|
+
docker:
|
|
5
|
+
- image: circleci/node:8.9.4
|
|
6
|
+
steps:
|
|
7
|
+
- checkout
|
|
8
|
+
- restore_cache:
|
|
9
|
+
keys:
|
|
10
|
+
- v1-dependencies-{{ checksum "package.json" }}
|
|
11
|
+
# fallback to using the latest cache if no exact match is found
|
|
12
|
+
- v1-dependencies-
|
|
13
|
+
- run: npm i
|
|
14
|
+
- save_cache:
|
|
15
|
+
paths:
|
|
16
|
+
- node_modules
|
|
17
|
+
key: v1-dependencies-{{ checksum "package.json" }}
|
|
18
|
+
- run: npm run coverage
|
|
19
|
+
- run: rm -rf ./coverage
|
|
20
|
+
- run: npm run linter
|
|
21
|
+
|
|
22
|
+
workflows:
|
|
23
|
+
version: 2
|
|
24
|
+
build_and_test:
|
|
25
|
+
jobs:
|
|
26
|
+
- test
|
package/index.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const axiosRetry = require('axios-retry');
|
|
3
|
+
const { Logger } = require('@autofleet/node-common');
|
|
4
|
+
const qs = require('qs');
|
|
5
|
+
const httpAdapter = require('axios/lib/adapters/http');
|
|
6
|
+
require('dotenv').config();
|
|
7
|
+
/**
|
|
8
|
+
* Add support for nock testing
|
|
9
|
+
* see s://github.com/axios/axios/issues/305
|
|
10
|
+
*/
|
|
11
|
+
if (process.env.NODE_ENV === 'test') {
|
|
12
|
+
axios.defaults.adapter = httpAdapter;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const HTTPMethods = [
|
|
16
|
+
'get',
|
|
17
|
+
'post',
|
|
18
|
+
'delete',
|
|
19
|
+
'head',
|
|
20
|
+
'put',
|
|
21
|
+
'patch',
|
|
22
|
+
'options',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const defaultSettings = {
|
|
26
|
+
timeout: 2500,
|
|
27
|
+
headers: { 'X-AF-AUTH': 'ANYONE' },
|
|
28
|
+
paramsSerializer: params => qs.stringify(params, { arrayFormat: 'brackets' }),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = class Network {
|
|
32
|
+
constructor(settings = {}) {
|
|
33
|
+
this.settings = Object.assign({}, defaultSettings, settings);
|
|
34
|
+
this.createBaseUrl();
|
|
35
|
+
|
|
36
|
+
this.axios = axios.create(this.settings);
|
|
37
|
+
this.addRetry(settings);
|
|
38
|
+
this.buildClassHttpMethods();
|
|
39
|
+
this.addLogs();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
addRetry(settings) {
|
|
43
|
+
axiosRetry(this.axios, {
|
|
44
|
+
retries: 0,
|
|
45
|
+
retryDelay: axiosRetry.exponentialDelay,
|
|
46
|
+
...settings,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addLogs() {
|
|
51
|
+
const logger = Logger();
|
|
52
|
+
this.axios.interceptors.request.use((request) => {
|
|
53
|
+
logger.info(`Start Request: [${request.method.toUpperCase()}] ${request.baseURL} ${request.url}`, {
|
|
54
|
+
headers: request.headers,
|
|
55
|
+
query: request.query,
|
|
56
|
+
body: request.body,
|
|
57
|
+
});
|
|
58
|
+
return request;
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
this.axios.interceptors.response.use((response) => {
|
|
62
|
+
logger.info(`Finish Request: [${response.config.method.toUpperCase()} ${response.config.url}`);
|
|
63
|
+
return response;
|
|
64
|
+
}, (error) => {
|
|
65
|
+
logger.error('Finish Request with error', { status: error.status, data: error.response && error.response.data });
|
|
66
|
+
throw error;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
createBaseUrl() {
|
|
71
|
+
if (!this.settings.serviceUrl && !this.settings.serviceName) {
|
|
72
|
+
throw new Error('At least one of the settings Missing serviceUrl or serviceName');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { settings } = this;
|
|
76
|
+
if (settings.serviceUrl) {
|
|
77
|
+
settings.baseURL = settings.serviceUrl;
|
|
78
|
+
} else if (settings.serviceName) {
|
|
79
|
+
const envServiceHostName = `${settings.serviceName}_SERVICE_HOST`;
|
|
80
|
+
settings.baseURL = `http://${process.env[envServiceHostName]}`;
|
|
81
|
+
if (!settings.baseURL) {
|
|
82
|
+
throw new Error(`Missing environment variable: ${envServiceHostName}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Build class methods that wrap axios methods
|
|
89
|
+
*/
|
|
90
|
+
buildClassHttpMethods() {
|
|
91
|
+
HTTPMethods.forEach((method) => {
|
|
92
|
+
this[method] = (...args) => this.axios[method](...args);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
package/index.test.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const nock = require('nock');
|
|
2
|
+
const Network = require('./index');
|
|
3
|
+
|
|
4
|
+
nock('http://www.google.com')
|
|
5
|
+
.get('/resource')
|
|
6
|
+
.reply(200, { one: 1 });
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
nock('https://www.apple.com')
|
|
10
|
+
.get('/resource')
|
|
11
|
+
.reply(200, { two: 2 });
|
|
12
|
+
|
|
13
|
+
describe('Network', () => {
|
|
14
|
+
it('Making requests by service name from ENV', async () => {
|
|
15
|
+
process.env.TEST_SERVICE_HOST = 'www.google.com';
|
|
16
|
+
const n = new Network({ serviceName: 'TEST' });
|
|
17
|
+
const response = await n.get('/resource');
|
|
18
|
+
expect(response).toBeDefined();
|
|
19
|
+
expect(response.data).toBeDefined();
|
|
20
|
+
expect(response.data.one).toBe(1);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('Making requests by service name from url', async () => {
|
|
24
|
+
const n = new Network({ serviceUrl: 'https://www.apple.com' });
|
|
25
|
+
const response = await n.get('/resource');
|
|
26
|
+
expect(response).toBeDefined();
|
|
27
|
+
expect(response.data).toBeDefined();
|
|
28
|
+
expect(response.data.two).toBe(2);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('Getting 404', async () => {
|
|
32
|
+
const n = new Network({ serviceUrl: 'https://www.apple.com' });
|
|
33
|
+
|
|
34
|
+
const action = async () => n.get('/resource', {
|
|
35
|
+
query: {
|
|
36
|
+
a: 'b',
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(action()).rejects.toThrow(Error);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('Retry 1 time', async () => {
|
|
44
|
+
nock('https://www.apple2.com')
|
|
45
|
+
.get('/resource')
|
|
46
|
+
.once()
|
|
47
|
+
.reply(500);
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
nock('https://www.apple2.com')
|
|
51
|
+
.get('/resource')
|
|
52
|
+
.once()
|
|
53
|
+
.reply(200, { two: 2 });
|
|
54
|
+
|
|
55
|
+
const n = new Network({ serviceUrl: 'https://www.apple2.com' });
|
|
56
|
+
const response = await n.get('/resource', {
|
|
57
|
+
query: {
|
|
58
|
+
a: 'b',
|
|
59
|
+
},
|
|
60
|
+
'axios-retry': {
|
|
61
|
+
retries: 1,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
expect(response).toBeDefined();
|
|
66
|
+
expect(response.data).toBeDefined();
|
|
67
|
+
expect(response.data.two).toBe(2);
|
|
68
|
+
});
|
|
69
|
+
});
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@autofleet/network",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "jest --forceExit --runInBand",
|
|
8
|
+
"test-auto": "jest --watch --runInBand",
|
|
9
|
+
"linter": "./node_modules/.bin/eslint ."
|
|
10
|
+
},
|
|
11
|
+
"author": "Dor Shay",
|
|
12
|
+
"license": "ISC",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@autofleet/node-common": "^1.1.50",
|
|
15
|
+
"axios": "^0.18.0",
|
|
16
|
+
"axios-retry": "^3.1.1",
|
|
17
|
+
"dotenv": "^6.0.0",
|
|
18
|
+
"qs": "^6.5.2"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"jest": "22.4.3",
|
|
22
|
+
"nock": "^10.0.0"
|
|
23
|
+
}
|
|
24
|
+
}
|