@k03mad/request 2.0.0 → 2.2.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/app/lib/curl.js +0 -3
- package/app/lib/queue.js +3 -11
- package/app/lib/request.js +45 -62
- package/package.json +2 -2
package/app/lib/curl.js
CHANGED
|
@@ -4,7 +4,6 @@ import prettyBytes from 'pretty-bytes';
|
|
|
4
4
|
const {bgWhite, black, blue, dim, green, magenta, red, white, yellow} = chalk;
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Сформировать curl-строку из опций got
|
|
8
7
|
* @param {string} url
|
|
9
8
|
* @param {object} [opts]
|
|
10
9
|
* @param {string} [opts.method]
|
|
@@ -25,12 +24,10 @@ export default (url, {
|
|
|
25
24
|
}, res) => {
|
|
26
25
|
const msg = [];
|
|
27
26
|
|
|
28
|
-
// если третий параметр — объект ошибки, то все необходимое на уровень ниже, в ключе response
|
|
29
27
|
if (res?.response) {
|
|
30
28
|
res = res.response;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
// 200 [800 ms] [3.15 kB]
|
|
34
31
|
if (res?.statusCode) {
|
|
35
32
|
msg.push(bgWhite(black(res.statusCode)));
|
|
36
33
|
}
|
package/app/lib/queue.js
CHANGED
|
@@ -6,9 +6,9 @@ const debug = _debug('mad:queue');
|
|
|
6
6
|
// const rps = num => ({intervalCap: num, interval: 1000});
|
|
7
7
|
const concurrency = num => ({concurrency: num});
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
9
|
+
// first level — host
|
|
10
|
+
// second level — method
|
|
11
|
+
// third level — p-queue options
|
|
12
12
|
const requestQueue = {
|
|
13
13
|
'*': {
|
|
14
14
|
'*': concurrency(3),
|
|
@@ -16,7 +16,6 @@ const requestQueue = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Поставить логирование и вернуть очередь
|
|
20
19
|
* @param {string} host
|
|
21
20
|
* @param {string} method
|
|
22
21
|
* @param {object} opts
|
|
@@ -44,20 +43,16 @@ const getLoggedQueue = (host, method, opts) => {
|
|
|
44
43
|
};
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
|
-
* Получить очередь по хосту и методу
|
|
48
46
|
* @param {string} host
|
|
49
47
|
* @param {string} method
|
|
50
48
|
* @returns {object}
|
|
51
49
|
*/
|
|
52
50
|
export default (host, method = 'GET') => {
|
|
53
|
-
// проверка на предустановленные настройки очереди для хоста и метода
|
|
54
51
|
for (const elem of [method, '*']) {
|
|
55
|
-
// очередь уже проинициализирована
|
|
56
52
|
if (requestQueue[host]?.[elem]?._events) {
|
|
57
53
|
return requestQueue[host][elem];
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
// очередь нужно проинициализировать
|
|
61
56
|
if (requestQueue[host]?.[elem]) {
|
|
62
57
|
const opts = requestQueue[host][elem];
|
|
63
58
|
requestQueue[host][elem] = new PQueue(opts);
|
|
@@ -65,21 +60,18 @@ export default (host, method = 'GET') => {
|
|
|
65
60
|
}
|
|
66
61
|
}
|
|
67
62
|
|
|
68
|
-
// инициализация очереди для хоста без текущего метода в предустановках
|
|
69
63
|
if (requestQueue[host]) {
|
|
70
64
|
const opts = requestQueue['*']['*'];
|
|
71
65
|
requestQueue[host]['*'] = new PQueue(opts);
|
|
72
66
|
return getLoggedQueue(host, '*', opts);
|
|
73
67
|
}
|
|
74
68
|
|
|
75
|
-
// инициализация очереди для хоста с методом из предустановок для всех очередей
|
|
76
69
|
if (requestQueue['*'][method]) {
|
|
77
70
|
const opts = requestQueue['*'][method];
|
|
78
71
|
requestQueue[host] = {[method]: new PQueue(opts)};
|
|
79
72
|
return getLoggedQueue(host, method, opts);
|
|
80
73
|
}
|
|
81
74
|
|
|
82
|
-
// нет ни хоста не метода в предустановках
|
|
83
75
|
const opts = requestQueue['*']['*'];
|
|
84
76
|
requestQueue[host] = {'*': new PQueue(opts)};
|
|
85
77
|
return getLoggedQueue(host, '*', opts);
|
package/app/lib/request.js
CHANGED
|
@@ -8,38 +8,37 @@ import getQueue from './queue.js';
|
|
|
8
8
|
const {blue, cyan, dim, green, red, yellow} = chalk;
|
|
9
9
|
const debug = _debug('mad:request');
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
11
|
+
const gotCache = new Map();
|
|
12
|
+
|
|
13
|
+
const cacheGotResponseKeys = [
|
|
14
|
+
'body',
|
|
15
|
+
'headers',
|
|
16
|
+
'method',
|
|
17
|
+
'statusCode',
|
|
18
|
+
'statusMessage',
|
|
19
|
+
'timings',
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const gotDefaultOpts = got.extend({
|
|
23
|
+
dnsCache: true,
|
|
24
|
+
timeout: {request: 15_000},
|
|
25
|
+
headers: {'user-agent': 'curl/7.81.0'},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const cacheDebug = msgArr => {
|
|
29
|
+
if (process.env.DEBUG) {
|
|
30
|
+
debug(msgArr.join(' :: '));
|
|
29
31
|
}
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
|
-
* Отправить запрос
|
|
34
35
|
* @param {string} url
|
|
35
36
|
* @param {object} opts
|
|
36
37
|
* @returns {object}
|
|
37
38
|
*/
|
|
38
39
|
const sendRequest = async (url, opts) => {
|
|
39
|
-
prepareRequestOpts(opts);
|
|
40
|
-
|
|
41
40
|
try {
|
|
42
|
-
const response = await
|
|
41
|
+
const response = await gotDefaultOpts(url, opts);
|
|
43
42
|
|
|
44
43
|
if (!opts.responseType) {
|
|
45
44
|
try {
|
|
@@ -52,22 +51,25 @@ const sendRequest = async (url, opts) => {
|
|
|
52
51
|
} catch (err) {
|
|
53
52
|
debug(getCurl(url, opts, err));
|
|
54
53
|
|
|
55
|
-
err.
|
|
56
|
-
|
|
57
|
-
err.__pretty.req = [
|
|
58
|
-
err?.response?.statusCode,
|
|
54
|
+
err.__req = [
|
|
55
|
+
err?.response?.statusCode || err?.code,
|
|
59
56
|
err?.options?.method,
|
|
60
57
|
url,
|
|
61
|
-
|
|
62
|
-
].join(' ');
|
|
58
|
+
].join(' ').trim();
|
|
63
59
|
|
|
64
|
-
err
|
|
60
|
+
if (err?.response?.ip) {
|
|
61
|
+
err.__ip = err.response.ip;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (Object.keys(opts).length > 0) {
|
|
65
|
+
err.__opts = opts;
|
|
66
|
+
}
|
|
65
67
|
|
|
66
68
|
if (err?.response?.body) {
|
|
67
69
|
try {
|
|
68
|
-
err.
|
|
70
|
+
err.__res = JSON.parse(err.response.body);
|
|
69
71
|
} catch {
|
|
70
|
-
err.
|
|
72
|
+
err.__res = err.response.body;
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -79,21 +81,12 @@ const sendRequest = async (url, opts) => {
|
|
|
79
81
|
}
|
|
80
82
|
};
|
|
81
83
|
|
|
82
|
-
export const cache = new Map();
|
|
83
|
-
|
|
84
84
|
/**
|
|
85
|
-
* Отправить запрос c выбором использования очереди
|
|
86
85
|
* @param {string} url
|
|
87
86
|
* @param {object} [opts]
|
|
88
|
-
* @param {object} [params]
|
|
89
|
-
* @param {boolean} [params.skipQueue]
|
|
90
87
|
* @returns {Promise<object>}
|
|
91
88
|
*/
|
|
92
|
-
export const request = (url, opts = {}
|
|
93
|
-
if (skipQueue) {
|
|
94
|
-
return sendRequest(url, opts);
|
|
95
|
-
}
|
|
96
|
-
|
|
89
|
+
export const request = (url, opts = {}) => {
|
|
97
90
|
const queue = getQueue(new URL(url).host, opts.method);
|
|
98
91
|
return queue.add(() => sendRequest(url, opts));
|
|
99
92
|
};
|
|
@@ -110,41 +103,31 @@ export const requestCache = (url, opts = {}, {cacheBy, expire = 43_200} = {}) =>
|
|
|
110
103
|
const queue = getQueue(new URL(url).host, opts.method);
|
|
111
104
|
|
|
112
105
|
return queue.add(async () => {
|
|
113
|
-
prepareRequestOpts(opts);
|
|
114
|
-
|
|
115
|
-
const cacheGotResponseKeys = [
|
|
116
|
-
'body',
|
|
117
|
-
'headers',
|
|
118
|
-
'method',
|
|
119
|
-
'statusCode',
|
|
120
|
-
'statusMessage',
|
|
121
|
-
'timings',
|
|
122
|
-
];
|
|
123
|
-
|
|
124
106
|
const cacheKey = `${url}::${JSON.stringify(cacheBy || opts)}`;
|
|
125
|
-
const
|
|
107
|
+
const urlLog = `${blue(url)}\n${dim(cacheKey)}`;
|
|
126
108
|
|
|
127
109
|
try {
|
|
128
|
-
if (
|
|
129
|
-
const {cachedResponse, date} =
|
|
110
|
+
if (gotCache.has(cacheKey)) {
|
|
111
|
+
const {cachedResponse, date} = gotCache.get(cacheKey);
|
|
130
112
|
|
|
131
113
|
const measurement = 'seconds';
|
|
132
114
|
const currentDiff = Math.round((Date.now() - date) / 1000);
|
|
115
|
+
const diffLog = `${currentDiff}/${expire} ${measurement} left`;
|
|
133
116
|
|
|
134
117
|
if (currentDiff < expire) {
|
|
135
|
-
|
|
118
|
+
cacheDebug([green('FROM CACHE'), diffLog, urlLog]);
|
|
136
119
|
return {cacheKey, ...cachedResponse};
|
|
137
120
|
}
|
|
138
121
|
|
|
139
|
-
|
|
122
|
+
cacheDebug([yellow('CACHE EXPIRED'), diffLog, urlLog]);
|
|
140
123
|
} else {
|
|
141
|
-
|
|
124
|
+
cacheDebug([blue('CACHE NOT FOUND'), urlLog]);
|
|
142
125
|
}
|
|
143
126
|
} catch (err) {
|
|
144
|
-
|
|
127
|
+
cacheDebug([red('CACHE ERROR'), dim(err), urlLog]);
|
|
145
128
|
}
|
|
146
129
|
|
|
147
|
-
const res = await
|
|
130
|
+
const res = await sendRequest(url, opts);
|
|
148
131
|
|
|
149
132
|
const cachedResponse = {};
|
|
150
133
|
|
|
@@ -152,8 +135,8 @@ export const requestCache = (url, opts = {}, {cacheBy, expire = 43_200} = {}) =>
|
|
|
152
135
|
cachedResponse[key] = res[key];
|
|
153
136
|
});
|
|
154
137
|
|
|
155
|
-
|
|
156
|
-
|
|
138
|
+
gotCache.set(cacheKey, {date: Date.now(), cachedResponse});
|
|
139
|
+
cacheDebug([cyan('CACHE SAVED'), urlLog]);
|
|
157
140
|
|
|
158
141
|
return res;
|
|
159
142
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@k03mad/request",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Request library",
|
|
5
5
|
"maintainers": [
|
|
6
6
|
"Kirill Molchanov <k03.mad@gmail.com"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"pretty-bytes": "6.1.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@k03mad/eslint-config": "12.0.
|
|
23
|
+
"@k03mad/eslint-config": "12.0.6",
|
|
24
24
|
"@microsoft/eslint-formatter-sarif": "3.0.0",
|
|
25
25
|
"eslint": "8.46.0",
|
|
26
26
|
"eslint-plugin-import": "2.28.0",
|