@algolia/requester-node-http 4.25.2 → 4.26.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.
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var http = require('http');
|
|
6
6
|
var https = require('https');
|
|
7
7
|
var URL = require('url');
|
|
8
|
+
var zlib = require('zlib');
|
|
8
9
|
|
|
9
10
|
/* eslint functional/prefer-readonly-type: 0 */
|
|
10
11
|
const agentOptions = { keepAlive: true };
|
|
@@ -18,6 +19,12 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
18
19
|
return new Promise(resolve => {
|
|
19
20
|
const url = URL.parse(request.url);
|
|
20
21
|
const path = url.query === null ? url.pathname : `${url.pathname}?${url.query}`;
|
|
22
|
+
const COMPRESSION_THRESHOLD = 750;
|
|
23
|
+
const acceptEncoding = request.headers['accept-encoding'];
|
|
24
|
+
const shouldCompress = request.data !== undefined &&
|
|
25
|
+
Buffer.byteLength(request.data) >= COMPRESSION_THRESHOLD &&
|
|
26
|
+
acceptEncoding !== undefined &&
|
|
27
|
+
acceptEncoding.toLowerCase().includes('gzip');
|
|
21
28
|
const options = {
|
|
22
29
|
...requesterOptions,
|
|
23
30
|
agent: url.protocol === 'https:' ? httpsAgent : httpAgent,
|
|
@@ -27,30 +34,62 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
27
34
|
headers: {
|
|
28
35
|
...(requesterOptions && requesterOptions.headers ? requesterOptions.headers : {}),
|
|
29
36
|
...request.headers,
|
|
37
|
+
...(shouldCompress ? { 'content-encoding': 'gzip' } : {}),
|
|
30
38
|
},
|
|
31
39
|
...(url.port !== undefined ? { port: url.port || '' } : {}),
|
|
32
40
|
};
|
|
41
|
+
// eslint-disable-next-line functional/no-let, prefer-const
|
|
42
|
+
let connectTimeout;
|
|
43
|
+
// eslint-disable-next-line functional/no-let
|
|
44
|
+
let responseTimeout;
|
|
45
|
+
// eslint-disable-next-line functional/no-let
|
|
46
|
+
let gunzip;
|
|
47
|
+
const cleanup = () => {
|
|
48
|
+
clearTimeout(connectTimeout);
|
|
49
|
+
clearTimeout(responseTimeout);
|
|
50
|
+
if (gunzip) {
|
|
51
|
+
gunzip.destroy();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const onError = (error) => {
|
|
55
|
+
cleanup();
|
|
56
|
+
resolve({ status: 0, content: error.message, isTimedOut: false });
|
|
57
|
+
};
|
|
33
58
|
const req = (url.protocol === 'https:' ? https : http).request(options, response => {
|
|
59
|
+
const contentEncoding = response.headers['content-encoding'];
|
|
60
|
+
const isGzipResponse = contentEncoding !== undefined && contentEncoding.toLowerCase().includes('gzip');
|
|
34
61
|
// eslint-disable-next-line functional/no-let
|
|
35
62
|
let contentBuffers = [];
|
|
36
|
-
|
|
63
|
+
const onData = (chunk) => {
|
|
37
64
|
contentBuffers = contentBuffers.concat(chunk);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
clearTimeout(connectTimeout);
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
43
|
-
clearTimeout(responseTimeout);
|
|
65
|
+
};
|
|
66
|
+
const onEnd = () => {
|
|
67
|
+
cleanup();
|
|
44
68
|
resolve({
|
|
45
69
|
status: response.statusCode || 0,
|
|
46
70
|
content: Buffer.concat(contentBuffers).toString(),
|
|
47
71
|
isTimedOut: false,
|
|
48
72
|
});
|
|
49
|
-
}
|
|
73
|
+
};
|
|
74
|
+
response.on('error', onError);
|
|
75
|
+
if (isGzipResponse) {
|
|
76
|
+
gunzip = zlib.createGunzip();
|
|
77
|
+
response.pipe(gunzip);
|
|
78
|
+
gunzip.on('data', onData);
|
|
79
|
+
gunzip.on('end', onEnd);
|
|
80
|
+
gunzip.on('error', onError);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
response.on('data', onData);
|
|
84
|
+
response.on('end', onEnd);
|
|
85
|
+
}
|
|
50
86
|
});
|
|
51
87
|
const createTimeout = (timeout, content) => {
|
|
52
88
|
return setTimeout(() => {
|
|
53
89
|
req.abort();
|
|
90
|
+
if (gunzip) {
|
|
91
|
+
gunzip.destroy();
|
|
92
|
+
}
|
|
54
93
|
resolve({
|
|
55
94
|
status: 0,
|
|
56
95
|
content,
|
|
@@ -58,22 +97,30 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
58
97
|
});
|
|
59
98
|
}, timeout * 1000);
|
|
60
99
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
let responseTimeout;
|
|
64
|
-
req.on('error', error => {
|
|
65
|
-
clearTimeout(connectTimeout);
|
|
66
|
-
clearTimeout(responseTimeout);
|
|
67
|
-
resolve({ status: 0, content: error.message, isTimedOut: false });
|
|
68
|
-
});
|
|
100
|
+
connectTimeout = createTimeout(request.connectTimeout, 'Connection timeout');
|
|
101
|
+
req.on('error', onError);
|
|
69
102
|
req.once('response', () => {
|
|
70
103
|
clearTimeout(connectTimeout);
|
|
71
104
|
responseTimeout = createTimeout(request.responseTimeout, 'Socket timeout');
|
|
72
105
|
});
|
|
73
|
-
if (request.data !== undefined) {
|
|
74
|
-
|
|
106
|
+
if (request.data !== undefined && shouldCompress) {
|
|
107
|
+
zlib.gzip(request.data, (error, compressedBody) => {
|
|
108
|
+
if (error) {
|
|
109
|
+
onError(error);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
req.setHeader('content-length', compressedBody.byteLength);
|
|
113
|
+
req.write(compressedBody);
|
|
114
|
+
req.end();
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
if (request.data !== undefined) {
|
|
119
|
+
req.setHeader('content-length', Buffer.byteLength(request.data));
|
|
120
|
+
req.write(request.data);
|
|
121
|
+
}
|
|
122
|
+
req.end();
|
|
75
123
|
}
|
|
76
|
-
req.end();
|
|
77
124
|
});
|
|
78
125
|
},
|
|
79
126
|
destroy() {
|
|
@@ -3,6 +3,7 @@ import { Agent } from 'http';
|
|
|
3
3
|
import * as https from 'https';
|
|
4
4
|
import { Agent as Agent$1 } from 'https';
|
|
5
5
|
import { parse } from 'url';
|
|
6
|
+
import { createGunzip, gzip } from 'zlib';
|
|
6
7
|
|
|
7
8
|
/* eslint functional/prefer-readonly-type: 0 */
|
|
8
9
|
const agentOptions = { keepAlive: true };
|
|
@@ -16,6 +17,12 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
16
17
|
return new Promise(resolve => {
|
|
17
18
|
const url = parse(request.url);
|
|
18
19
|
const path = url.query === null ? url.pathname : `${url.pathname}?${url.query}`;
|
|
20
|
+
const COMPRESSION_THRESHOLD = 750;
|
|
21
|
+
const acceptEncoding = request.headers['accept-encoding'];
|
|
22
|
+
const shouldCompress = request.data !== undefined &&
|
|
23
|
+
Buffer.byteLength(request.data) >= COMPRESSION_THRESHOLD &&
|
|
24
|
+
acceptEncoding !== undefined &&
|
|
25
|
+
acceptEncoding.toLowerCase().includes('gzip');
|
|
19
26
|
const options = {
|
|
20
27
|
...requesterOptions,
|
|
21
28
|
agent: url.protocol === 'https:' ? httpsAgent : httpAgent,
|
|
@@ -25,30 +32,62 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
25
32
|
headers: {
|
|
26
33
|
...(requesterOptions && requesterOptions.headers ? requesterOptions.headers : {}),
|
|
27
34
|
...request.headers,
|
|
35
|
+
...(shouldCompress ? { 'content-encoding': 'gzip' } : {}),
|
|
28
36
|
},
|
|
29
37
|
...(url.port !== undefined ? { port: url.port || '' } : {}),
|
|
30
38
|
};
|
|
39
|
+
// eslint-disable-next-line functional/no-let, prefer-const
|
|
40
|
+
let connectTimeout;
|
|
41
|
+
// eslint-disable-next-line functional/no-let
|
|
42
|
+
let responseTimeout;
|
|
43
|
+
// eslint-disable-next-line functional/no-let
|
|
44
|
+
let gunzip;
|
|
45
|
+
const cleanup = () => {
|
|
46
|
+
clearTimeout(connectTimeout);
|
|
47
|
+
clearTimeout(responseTimeout);
|
|
48
|
+
if (gunzip) {
|
|
49
|
+
gunzip.destroy();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const onError = (error) => {
|
|
53
|
+
cleanup();
|
|
54
|
+
resolve({ status: 0, content: error.message, isTimedOut: false });
|
|
55
|
+
};
|
|
31
56
|
const req = (url.protocol === 'https:' ? https : http).request(options, response => {
|
|
57
|
+
const contentEncoding = response.headers['content-encoding'];
|
|
58
|
+
const isGzipResponse = contentEncoding !== undefined && contentEncoding.toLowerCase().includes('gzip');
|
|
32
59
|
// eslint-disable-next-line functional/no-let
|
|
33
60
|
let contentBuffers = [];
|
|
34
|
-
|
|
61
|
+
const onData = (chunk) => {
|
|
35
62
|
contentBuffers = contentBuffers.concat(chunk);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
clearTimeout(connectTimeout);
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
41
|
-
clearTimeout(responseTimeout);
|
|
63
|
+
};
|
|
64
|
+
const onEnd = () => {
|
|
65
|
+
cleanup();
|
|
42
66
|
resolve({
|
|
43
67
|
status: response.statusCode || 0,
|
|
44
68
|
content: Buffer.concat(contentBuffers).toString(),
|
|
45
69
|
isTimedOut: false,
|
|
46
70
|
});
|
|
47
|
-
}
|
|
71
|
+
};
|
|
72
|
+
response.on('error', onError);
|
|
73
|
+
if (isGzipResponse) {
|
|
74
|
+
gunzip = createGunzip();
|
|
75
|
+
response.pipe(gunzip);
|
|
76
|
+
gunzip.on('data', onData);
|
|
77
|
+
gunzip.on('end', onEnd);
|
|
78
|
+
gunzip.on('error', onError);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
response.on('data', onData);
|
|
82
|
+
response.on('end', onEnd);
|
|
83
|
+
}
|
|
48
84
|
});
|
|
49
85
|
const createTimeout = (timeout, content) => {
|
|
50
86
|
return setTimeout(() => {
|
|
51
87
|
req.abort();
|
|
88
|
+
if (gunzip) {
|
|
89
|
+
gunzip.destroy();
|
|
90
|
+
}
|
|
52
91
|
resolve({
|
|
53
92
|
status: 0,
|
|
54
93
|
content,
|
|
@@ -56,22 +95,30 @@ function createNodeHttpRequester({ agent: userGlobalAgent, httpAgent: userHttpAg
|
|
|
56
95
|
});
|
|
57
96
|
}, timeout * 1000);
|
|
58
97
|
};
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
let responseTimeout;
|
|
62
|
-
req.on('error', error => {
|
|
63
|
-
clearTimeout(connectTimeout);
|
|
64
|
-
clearTimeout(responseTimeout);
|
|
65
|
-
resolve({ status: 0, content: error.message, isTimedOut: false });
|
|
66
|
-
});
|
|
98
|
+
connectTimeout = createTimeout(request.connectTimeout, 'Connection timeout');
|
|
99
|
+
req.on('error', onError);
|
|
67
100
|
req.once('response', () => {
|
|
68
101
|
clearTimeout(connectTimeout);
|
|
69
102
|
responseTimeout = createTimeout(request.responseTimeout, 'Socket timeout');
|
|
70
103
|
});
|
|
71
|
-
if (request.data !== undefined) {
|
|
72
|
-
|
|
104
|
+
if (request.data !== undefined && shouldCompress) {
|
|
105
|
+
gzip(request.data, (error, compressedBody) => {
|
|
106
|
+
if (error) {
|
|
107
|
+
onError(error);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
req.setHeader('content-length', compressedBody.byteLength);
|
|
111
|
+
req.write(compressedBody);
|
|
112
|
+
req.end();
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
if (request.data !== undefined) {
|
|
117
|
+
req.setHeader('content-length', Buffer.byteLength(request.data));
|
|
118
|
+
req.write(request.data);
|
|
119
|
+
}
|
|
120
|
+
req.end();
|
|
73
121
|
}
|
|
74
|
-
req.end();
|
|
75
122
|
});
|
|
76
123
|
},
|
|
77
124
|
destroy() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@algolia/requester-node-http",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.26.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Promise-based request library for node using the native http module.",
|
|
6
6
|
"repository": {
|
|
@@ -17,6 +17,6 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@algolia/requester-common": "4.
|
|
20
|
+
"@algolia/requester-common": "4.26.0"
|
|
21
21
|
}
|
|
22
22
|
}
|