makiwara 2.0.6 → 2.1.1
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/README.md +48 -50
- package/bin/cli.js +58 -14
- package/index.js +10 -6
- package/package.json +75 -69
- package/src/color-logs.js +0 -2
- package/src/display.js +15 -13
- package/src/http-status-codes.js +6 -0
- package/src/local-fetch.js +36 -0
- package/src/make-requests.js +84 -43
- package/src/object-util.js +0 -2
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# makiwara
|
|
1
|
+
# makiwara
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/js/makiwara)
|
|
4
4
|
[](https://www.npmjs.com/~piecioshka)
|
|
5
5
|
[](https://travis-ci.org/piecioshka/makiwara)
|
|
6
6
|
[](https://github.com/piecioshka/makiwara)
|
|
7
|
-
[](https://coveralls.io/github/piecioshka/makiwara?branch=master)
|
|
8
8
|
|
|
9
9
|
:hammer: Benchmark URL to gain HTTP requests limits
|
|
10
10
|
|
|
@@ -19,7 +19,7 @@ npm install -g makiwara
|
|
|
19
19
|
```javascript
|
|
20
20
|
const { attack } = require('makiwara');
|
|
21
21
|
|
|
22
|
-
attack('http
|
|
22
|
+
attack('http://example.org', [1, 5, 10], 'sequence')
|
|
23
23
|
.then((result) => {
|
|
24
24
|
console.log(result);
|
|
25
25
|
})
|
|
@@ -30,63 +30,61 @@ attack('http;//example.org', [1, 5, 10])
|
|
|
30
30
|
|
|
31
31
|
## CLI
|
|
32
32
|
|
|
33
|
-
```
|
|
33
|
+
```text
|
|
34
34
|
makiwara --help
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
Usage: cli [options]
|
|
37
37
|
|
|
38
|
+
Example:
|
|
39
|
+
makiwara -u http://localhost:3000 -t 10 -s sequence
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
Options:
|
|
42
|
+
-V, --version output the version number
|
|
43
|
+
-u, --url <url> Define URL to attack. Ex. http://example.org/
|
|
44
|
+
-t, --timelimit [numbers] Define list of time thresholds (in seconds). Ex. 10,100,1000
|
|
45
|
+
-s, --strategy <concurrent|sequence> Define strategy for making requests
|
|
46
|
+
-h, --help output usage information
|
|
47
|
+
```
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
## Example
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
makiwara -u https://example.org -t 1,5 -s sequence
|
|
45
53
|
```
|
|
46
54
|
|
|
55
|
+
Result:
|
|
56
|
+
|
|
47
57
|
```text
|
|
48
|
-
Requests summary of 1 second(s):
|
|
49
|
-
╔══════════════════════╤═══════════════════════════╗
|
|
50
|
-
║ HTTP Status Code │ Quantity ║
|
|
51
|
-
╟──────────────────────┼───────────────────────────╢
|
|
52
|
-
║ 200 OK │ 3 ║
|
|
53
|
-
╚══════════════════════╧═══════════════════════════╝
|
|
54
|
-
|
|
55
|
-
Attack summary of 1 second(s):
|
|
56
|
-
╔══════════════════════╤═══════════════════════════╗
|
|
57
|
-
║ Start time │ 2017-12-18T11:48:37.152Z ║
|
|
58
|
-
╟──────────────────────┼───────────────────────────╢
|
|
59
|
-
║ End time │ 2017-12-18T11:48:38.296Z ║
|
|
60
|
-
╟──────────────────────┼───────────────────────────╢
|
|
61
|
-
║ Duration │ 1144 ms ║
|
|
62
|
-
╟──────────────────────┼───────────────────────────╢
|
|
63
|
-
║ Time limit │ 1000 ms ║
|
|
64
|
-
╟──────────────────────┼───────────────────────────╢
|
|
65
|
-
║ Avg. request time │ 333.333 ms/req. ║
|
|
66
|
-
╚══════════════════════╧═══════════════════════════╝
|
|
67
58
|
|
|
68
|
-
|
|
59
|
+
╔════════════════════════╤════════════════════════════════╗
|
|
60
|
+
║ HTTP Status Code │ Requests quantity ║
|
|
61
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
62
|
+
║ 200 OK │ 3 ║
|
|
63
|
+
╚════════════════════════╧════════════════════════════════╝
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
║ Start time │ 2017-12-18T11:48:37.153Z ║
|
|
80
|
-
╟──────────────────────┼───────────────────────────╢
|
|
81
|
-
║ End time │ 2017-12-18T11:48:42.265Z ║
|
|
82
|
-
╟──────────────────────┼───────────────────────────╢
|
|
83
|
-
║ Duration │ 5112 ms ║
|
|
84
|
-
╟──────────────────────┼───────────────────────────╢
|
|
85
|
-
║ Time limit │ 5000 ms ║
|
|
86
|
-
╟──────────────────────┼───────────────────────────╢
|
|
87
|
-
║ Avg. request time │ 238.095 ms/req. ║
|
|
88
|
-
╚══════════════════════╧═══════════════════════════╝
|
|
65
|
+
╔════════════════════════╤════════════════════════════════╗
|
|
66
|
+
║ Type │ Sequence ║
|
|
67
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
68
|
+
║ Effective Duration │ 1.456 seconds ║
|
|
69
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
70
|
+
║ Times │ 3 ║
|
|
71
|
+
╚════════════════════════╧════════════════════════════════╝
|
|
72
|
+
|
|
73
|
+
----------------------------------------------------
|
|
89
74
|
|
|
75
|
+
╔════════════════════════╤════════════════════════════════╗
|
|
76
|
+
║ HTTP Status Code │ Requests quantity ║
|
|
77
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
78
|
+
║ 200 OK │ 10 ║
|
|
79
|
+
╚════════════════════════╧════════════════════════════════╝
|
|
80
|
+
|
|
81
|
+
╔════════════════════════╤════════════════════════════════╗
|
|
82
|
+
║ Type │ Sequence ║
|
|
83
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
84
|
+
║ Effective Duration │ 5.399 seconds ║
|
|
85
|
+
╟────────────────────────┼────────────────────────────────╢
|
|
86
|
+
║ Times │ 10 ║
|
|
87
|
+
╚════════════════════════╧════════════════════════════════╝
|
|
90
88
|
```
|
|
91
89
|
|
|
92
90
|
## Unit tests
|
|
@@ -103,4 +101,4 @@ npm run coverage
|
|
|
103
101
|
|
|
104
102
|
## License
|
|
105
103
|
|
|
106
|
-
[The MIT License](http://piecioshka.mit-license.org) @ 2017
|
|
104
|
+
[The MIT License](http://piecioshka.mit-license.org) @ 2017-2019
|
package/bin/cli.js
CHANGED
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
3
|
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const http = require('http');
|
|
7
|
+
const https = require('https');
|
|
8
|
+
http.globalAgent.maxSockets = https.globalAgent.maxSockets = 512;
|
|
9
|
+
// http.globalAgent.maxFreeSockets = https.globalAgent.maxFreeSockets = 512;
|
|
10
|
+
|
|
6
11
|
const program = require('commander');
|
|
7
12
|
const ora = require('ora');
|
|
8
13
|
const isUrl = require('is-url');
|
|
9
14
|
const bold = require('ansi-bold');
|
|
10
15
|
|
|
11
|
-
// eslint-disable-next-line no-sync
|
|
12
|
-
const pkg = fs.readFileSync('../package.json').toJSON();
|
|
13
16
|
const { attack } = require('../index');
|
|
17
|
+
const HTTP_STATUS = require('../src/http-status-codes');
|
|
14
18
|
const { displaySummary, displayError } = require('../src/display');
|
|
19
|
+
const { makeRequest } = require('../src/make-requests');
|
|
20
|
+
|
|
21
|
+
// eslint-disable-next-line no-sync
|
|
22
|
+
const pkg = JSON.parse(fs.readFileSync(
|
|
23
|
+
path.join(__dirname, '..', 'package.json')
|
|
24
|
+
).toString());
|
|
25
|
+
const STRATEGY_REGEXP = /^(concurrent|sequence)$/;
|
|
15
26
|
|
|
16
27
|
program
|
|
17
28
|
.version(pkg.version)
|
|
18
29
|
.option('-u, --url <url>', 'Define URL to attack. Ex. http://example.org/')
|
|
19
30
|
.option('-t, --timelimit [numbers]', 'Define list of time thresholds (in seconds). Ex. 10,100,1000')
|
|
31
|
+
.option('-s, --strategy <concurrent|sequence>', 'Define strategy for making requests')
|
|
32
|
+
.description('Example:\n\tmakiwara -u http://localhost:3000 -t 10 -s sequence')
|
|
20
33
|
.parse(process.argv);
|
|
21
34
|
|
|
22
35
|
if (typeof program.url !== 'string') {
|
|
23
|
-
console.red('
|
|
36
|
+
console.red('Error: url is not a string');
|
|
24
37
|
program.help();
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
if (!isUrl(program.url)) {
|
|
28
|
-
console.red(
|
|
41
|
+
console.red('Error: url is not correct format');
|
|
29
42
|
program.help();
|
|
30
43
|
}
|
|
31
44
|
|
|
@@ -35,8 +48,16 @@ if (!program.timelimit) {
|
|
|
35
48
|
console.yellow(`Thresholds are sets to: ${bold(program.timelimit)} (seconds)\n`);
|
|
36
49
|
}
|
|
37
50
|
|
|
51
|
+
if (!(STRATEGY_REGEXP).test(program.strategy)) {
|
|
52
|
+
program.strategy = 'concurrent';
|
|
53
|
+
console.yellow('Ups... you did not put "strategy"');
|
|
54
|
+
console.yellow(`Default strategy is: ${program.strategy}\n`);
|
|
55
|
+
}
|
|
56
|
+
|
|
38
57
|
const url = program.url;
|
|
39
58
|
const timeLimit = program.timelimit.split(',').map(Number);
|
|
59
|
+
const strategy = program.strategy;
|
|
60
|
+
let spinner = null;
|
|
40
61
|
|
|
41
62
|
function displayDelimiter() {
|
|
42
63
|
console.gray('----------------------------------------------------\n');
|
|
@@ -44,26 +65,49 @@ function displayDelimiter() {
|
|
|
44
65
|
|
|
45
66
|
function displayHeader() {
|
|
46
67
|
console.log(`${pkg.name}, Version ${pkg.version}`);
|
|
47
|
-
|
|
68
|
+
const currentYear = new Date().getFullYear();
|
|
69
|
+
console.log(`Copyright 2017-${currentYear} ${pkg.author.name} <${pkg.author.email}> ${pkg.author.url}`);
|
|
48
70
|
console.log(`The ${pkg.license} License, https://piecioshka.mit-license.org/\n`);
|
|
49
71
|
console.log(`> ${pkg.description}\n`);
|
|
50
72
|
}
|
|
51
73
|
|
|
52
|
-
|
|
74
|
+
async function sendTestRequest(testUrl) {
|
|
75
|
+
spinner.succeed(`Start testing... ${bold(testUrl)}`);
|
|
76
|
+
const response = await makeRequest(testUrl, { agent: false });
|
|
77
|
+
if (response.status !== HTTP_STATUS.OK) {
|
|
78
|
+
console.red(`HTTP Status Code: ${bold(response.status)}`);
|
|
79
|
+
console.yellow(`Response Body: ${bold(response.text)}`);
|
|
80
|
+
}
|
|
81
|
+
spinner.succeed(`Testing completed (response: ${bold(response.text.length)} Bytes)`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function main() {
|
|
85
|
+
displayHeader();
|
|
53
86
|
|
|
54
|
-
|
|
87
|
+
spinner = ora('Loading').start();
|
|
55
88
|
|
|
56
|
-
|
|
57
|
-
|
|
89
|
+
try {
|
|
90
|
+
await sendTestRequest(url);
|
|
91
|
+
|
|
92
|
+
spinner.succeed('Start attacking...');
|
|
93
|
+
const results = await attack(url, timeLimit, strategy);
|
|
58
94
|
spinner.stop();
|
|
95
|
+
spinner.succeed('Attacking completed\n');
|
|
96
|
+
|
|
59
97
|
results.forEach((result, index) => {
|
|
60
98
|
displaySummary(result);
|
|
99
|
+
|
|
61
100
|
if (index < results.length - 1) {
|
|
62
101
|
displayDelimiter();
|
|
63
102
|
}
|
|
64
103
|
});
|
|
65
|
-
})
|
|
66
|
-
.catch((err) => {
|
|
104
|
+
} catch (err) {
|
|
67
105
|
spinner.stop();
|
|
68
106
|
displayError(err);
|
|
69
|
-
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// eslint-disable-next-line no-process-exit
|
|
110
|
+
process.exit(0);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
main();
|
package/index.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const { makeRequests } = require('./src/make-requests');
|
|
1
|
+
const { makeRequestsInConcurrentMode, makeRequestsInSequenceMode } = require('./src/make-requests');
|
|
4
2
|
|
|
5
3
|
require('./src/color-logs');
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
const strategies = new Map();
|
|
6
|
+
strategies.set('sequence', makeRequestsInSequenceMode);
|
|
7
|
+
strategies.set('concurrent', makeRequestsInConcurrentMode);
|
|
8
|
+
|
|
9
|
+
function attack(url, timeLimits, strategy) {
|
|
10
|
+
const method = strategies.get(strategy);
|
|
11
|
+
|
|
9
12
|
return Promise.all(
|
|
10
13
|
timeLimits
|
|
14
|
+
// Remove zeros timeLimits
|
|
11
15
|
.filter((k) => k)
|
|
12
|
-
.map((duration) =>
|
|
16
|
+
.map((duration) => method(url, duration))
|
|
13
17
|
);
|
|
14
18
|
}
|
|
15
19
|
|
package/package.json
CHANGED
|
@@ -1,71 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"
|
|
70
|
-
"
|
|
2
|
+
"name": "makiwara",
|
|
3
|
+
"description": "Benchmark URL to gain HTTP requests limits",
|
|
4
|
+
"version": "2.1.1",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Piotr Kowalski",
|
|
8
|
+
"email": "piecioshka@gmail.com",
|
|
9
|
+
"url": "https://piecioshka.pl/"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"clear": "rm -rf dist/ coverage/ .nyc_output/",
|
|
13
|
+
"clear:all": "rm -rf node_modules/ && npm run clear",
|
|
14
|
+
"test": "jasmine test/specs/*.js",
|
|
15
|
+
"coverage": "nyc npm run test && nyc report --reporter=text-lcov | coveralls -v",
|
|
16
|
+
"lint": "eslint .",
|
|
17
|
+
"snyk-protect": "snyk protect",
|
|
18
|
+
"prepare": "npm run snyk-protect"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@types/node": "^17.0.0",
|
|
22
|
+
"ansi-bold": "^0.1.1",
|
|
23
|
+
"ansi-cyan": "^0.1.1",
|
|
24
|
+
"ansi-gray": "^0.1.1",
|
|
25
|
+
"ansi-red": "^0.1.1",
|
|
26
|
+
"ansi-yellow": "^0.1.1",
|
|
27
|
+
"axios": "^0.24.0",
|
|
28
|
+
"commander": "^8.3.0",
|
|
29
|
+
"http-status-codes": "^2.1.4",
|
|
30
|
+
"is-url": "^1.2.4",
|
|
31
|
+
"node-fetch": "^3.1.0",
|
|
32
|
+
"ora": "^6.0.1",
|
|
33
|
+
"snyk": "^1.797.0",
|
|
34
|
+
"table": "^6.7.5"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/jasmine": "^3.10.2",
|
|
38
|
+
"coveralls": "^3.1.1",
|
|
39
|
+
"eslint": "^8.5.0",
|
|
40
|
+
"eslint-config-piecioshka": "^2.0.4",
|
|
41
|
+
"jasmine": "^3.10.0",
|
|
42
|
+
"nock": "^13.2.1",
|
|
43
|
+
"nyc": "^15.1.0"
|
|
44
|
+
},
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "https://github.com/piecioshka/makiwara.git"
|
|
48
|
+
},
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://github.com/piecioshka/makiwara/issues"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"bin",
|
|
54
|
+
"src",
|
|
55
|
+
"index.js",
|
|
56
|
+
"package.json",
|
|
57
|
+
"README.md"
|
|
58
|
+
],
|
|
59
|
+
"keywords": [
|
|
60
|
+
"app",
|
|
61
|
+
"test",
|
|
62
|
+
"attack",
|
|
63
|
+
"multi",
|
|
64
|
+
"statistics",
|
|
65
|
+
"summary",
|
|
66
|
+
"metrics",
|
|
67
|
+
"verify",
|
|
68
|
+
"request",
|
|
69
|
+
"time",
|
|
70
|
+
"analyze",
|
|
71
|
+
"cli",
|
|
72
|
+
"commonjs"
|
|
73
|
+
],
|
|
74
|
+
"main": "./index.js",
|
|
75
|
+
"bin": "./bin/cli.js",
|
|
76
|
+
"snyk": true
|
|
71
77
|
}
|
package/src/color-logs.js
CHANGED
package/src/display.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const { table } = require('table');
|
|
4
2
|
const HTTPStatusCodes = require('http-status-codes');
|
|
5
3
|
const bold = require('ansi-bold');
|
|
6
4
|
|
|
7
5
|
const { collapseArray } = require('./object-util');
|
|
8
6
|
|
|
7
|
+
const SECOND_IN_MILLISECONDS = 1000;
|
|
8
|
+
|
|
9
9
|
const tableOptions = {
|
|
10
10
|
columns: {
|
|
11
|
-
0: { width:
|
|
11
|
+
0: { width: 22 },
|
|
12
12
|
1: { width: 30 }
|
|
13
13
|
}
|
|
14
14
|
};
|
|
@@ -29,26 +29,28 @@ function appendHttpStatusCodeLabel(statusCodeEntries) {
|
|
|
29
29
|
|
|
30
30
|
function displayRequestsSummary(attackResults) {
|
|
31
31
|
const statusCodes = collapseArray(
|
|
32
|
-
attackResults.requests.map((r) => r.
|
|
32
|
+
attackResults.requests.map((r) => r.status)
|
|
33
33
|
);
|
|
34
34
|
const isEmptyResults = (statusCodes.length === 0);
|
|
35
35
|
|
|
36
36
|
if (isEmptyResults) {
|
|
37
|
-
|
|
37
|
+
statusCodes['-'] = -1;
|
|
38
38
|
} else {
|
|
39
39
|
appendHttpStatusCodeLabel(statusCodes);
|
|
40
|
-
const data = [['HTTP Status Code', 'Requests quantity'].map(bold)]
|
|
41
|
-
.concat(statusCodes);
|
|
42
|
-
console.log(table(data, tableOptions));
|
|
43
40
|
}
|
|
41
|
+
|
|
42
|
+
const data = [['HTTP Status Code', 'Requests quantity']
|
|
43
|
+
.map(bold)]
|
|
44
|
+
.concat(statusCodes);
|
|
45
|
+
console.log(table(data, tableOptions));
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
function displayAttackSummary(
|
|
48
|
+
function displayAttackSummary(results) {
|
|
47
49
|
const meta = [];
|
|
48
|
-
meta.push(['
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
meta.push(['
|
|
50
|
+
meta.push(['Type', results.type]);
|
|
51
|
+
const durationInSeconds = (results.duration / SECOND_IN_MILLISECONDS);
|
|
52
|
+
meta.push(['Effective Duration', `${durationInSeconds.toLocaleString()} seconds`]);
|
|
53
|
+
meta.push(['Times', `${results.times}`]);
|
|
52
54
|
console.log(table(meta, tableOptions));
|
|
53
55
|
}
|
|
54
56
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
const IS_HTTP = (/^https/);
|
|
5
|
+
|
|
6
|
+
function getProtocol(url) {
|
|
7
|
+
if (IS_HTTP.test(url)) {
|
|
8
|
+
return https;
|
|
9
|
+
}
|
|
10
|
+
return http;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function makeRequest(url, options = {}) {
|
|
14
|
+
const response = {
|
|
15
|
+
status: null,
|
|
16
|
+
text: '',
|
|
17
|
+
};
|
|
18
|
+
const protocol = getProtocol(url);
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
protocol.get(url, options, (res) => {
|
|
21
|
+
res.addListener('data', (data) => {
|
|
22
|
+
response.text += data.toString();
|
|
23
|
+
});
|
|
24
|
+
res.addListener('error', (err) => {
|
|
25
|
+
reject(err);
|
|
26
|
+
});
|
|
27
|
+
res.addListener('end', () => {
|
|
28
|
+
response.status = res.statusCode;
|
|
29
|
+
resolve(response);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = makeRequest;
|
|
36
|
+
module.exports.makeRequest = makeRequest;
|
package/src/make-requests.js
CHANGED
|
@@ -1,70 +1,111 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return response.status;
|
|
13
|
-
} catch (err) {
|
|
14
|
-
if (err.response) {
|
|
15
|
-
return err.response.status;
|
|
16
|
-
}
|
|
17
|
-
return 0;
|
|
18
|
-
}
|
|
1
|
+
const http = require('http');
|
|
2
|
+
|
|
3
|
+
// const makeRequest = require('node-fetch');
|
|
4
|
+
const makeRequest = require('./local-fetch');
|
|
5
|
+
|
|
6
|
+
const SECOND_IN_MILLISECONDS = 1000;
|
|
7
|
+
|
|
8
|
+
function pause(timeoutInSeconds) {
|
|
9
|
+
return new Promise((resolve) => {
|
|
10
|
+
setTimeout(resolve, timeoutInSeconds * SECOND_IN_MILLISECONDS);
|
|
11
|
+
});
|
|
19
12
|
}
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
durationLimit = Number(durationLimit);
|
|
14
|
+
function status(i) {
|
|
15
|
+
if (global.spinner) {
|
|
16
|
+
global.spinner.text = `Loading: ${i} time(s)`;
|
|
17
|
+
global.spinner.render();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
28
20
|
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
async function makeRequestsInConcurrentMode(url, durationInSeconds) {
|
|
22
|
+
if (isNaN(durationInSeconds)) {
|
|
23
|
+
throw new TypeError('duration should be a number (ex. 1,3,5)');
|
|
31
24
|
}
|
|
32
25
|
|
|
33
|
-
const millisecondTimeLimit = durationLimit * 1000;
|
|
34
26
|
const requests = [];
|
|
35
27
|
const startTime = Date.now();
|
|
28
|
+
const durationInMilliseconds = durationInSeconds * SECOND_IN_MILLISECONDS;
|
|
29
|
+
let i = 0;
|
|
36
30
|
|
|
31
|
+
// eslint-disable-next-line no-constant-condition
|
|
37
32
|
while (true) {
|
|
38
|
-
const
|
|
39
|
-
const statusCode = await fetchStatusCode(url);
|
|
40
|
-
const endRequestTime = Date.now();
|
|
41
|
-
const requestDuration = (endRequestTime - startRequestTime);
|
|
33
|
+
const currentTime = Date.now();
|
|
42
34
|
|
|
43
|
-
|
|
44
|
-
|
|
35
|
+
if (i >= http.globalAgent.maxSockets) {
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
45
38
|
|
|
46
|
-
if (
|
|
39
|
+
if (currentTime > startTime + durationInMilliseconds) {
|
|
47
40
|
break;
|
|
48
41
|
}
|
|
49
42
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
i++;
|
|
44
|
+
|
|
45
|
+
status(i);
|
|
46
|
+
|
|
47
|
+
await makeRequest(url, { agent: false })
|
|
48
|
+
.then((response) => {
|
|
49
|
+
requests.push(response);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const endTime = Date.now();
|
|
54
|
+
const wholeProcessDuration = endTime - startTime;
|
|
55
|
+
|
|
56
|
+
await pause(durationInSeconds);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
type: 'Concurrent',
|
|
60
|
+
startTime,
|
|
61
|
+
endTime,
|
|
62
|
+
duration: wholeProcessDuration,
|
|
63
|
+
times: i,
|
|
64
|
+
requests
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function makeRequestsInSequenceMode(url, durationInSeconds) {
|
|
69
|
+
if (isNaN(durationInSeconds)) {
|
|
70
|
+
throw new TypeError('duration should be a number (ex. 1,3,5)');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const requests = [];
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
const durationInMilliseconds = durationInSeconds * SECOND_IN_MILLISECONDS;
|
|
76
|
+
let i = 0;
|
|
77
|
+
|
|
78
|
+
// eslint-disable-next-line no-constant-condition
|
|
79
|
+
while (true) {
|
|
80
|
+
const currentTime = Date.now();
|
|
81
|
+
|
|
82
|
+
if (currentTime > startTime + durationInMilliseconds) {
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
i++;
|
|
87
|
+
|
|
88
|
+
status(i);
|
|
89
|
+
|
|
90
|
+
const response = await makeRequest(url, { agent: false });
|
|
91
|
+
requests.push(response);
|
|
54
92
|
}
|
|
55
93
|
|
|
56
94
|
const endTime = Date.now();
|
|
57
|
-
const
|
|
95
|
+
const wholeProcessDuration = endTime - startTime;
|
|
58
96
|
|
|
59
97
|
return {
|
|
98
|
+
type: 'Sequence',
|
|
60
99
|
startTime,
|
|
61
100
|
endTime,
|
|
62
|
-
|
|
63
|
-
|
|
101
|
+
duration: wholeProcessDuration,
|
|
102
|
+
times: i,
|
|
64
103
|
requests
|
|
65
104
|
};
|
|
66
105
|
}
|
|
67
106
|
|
|
68
107
|
module.exports = {
|
|
69
|
-
|
|
108
|
+
makeRequest,
|
|
109
|
+
makeRequestsInSequenceMode,
|
|
110
|
+
makeRequestsInConcurrentMode
|
|
70
111
|
};
|