te.js 1.0.0 → 1.0.2
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/.prettierrc +4 -4
- package/database/index.js +7 -7
- package/database/mongo.js +67 -14
- package/example/index.js +4 -6
- package/example/middlewares/global.midair.js +6 -0
- package/example/package.json +3 -2
- package/example/{routes → targets}/index.target.js +11 -10
- package/example/targets/user/user.target.js +17 -0
- package/example/tejas.config.json +5 -2
- package/package.json +36 -34
- package/server/ammo/body-parser.js +93 -51
- package/server/ammo/dispatch-helper.js +53 -53
- package/server/ammo/enhancer.js +53 -53
- package/server/ammo.js +96 -95
- package/server/error.js +9 -0
- package/server/files/helper.js +33 -0
- package/server/files/uploader.js +142 -0
- package/server/handler.js +71 -70
- package/server/target.js +62 -62
- package/server/targets/middleware-validator.js +22 -22
- package/server/targets/registry.js +44 -44
- package/te.js +128 -106
- package/utils/auto-register.js +26 -0
- package/utils/configuration.js +61 -61
- package/utils/request-logger.js +43 -43
- package/utils/status-codes.js +82 -82
- package/utils/tejas-entrypoint-html.js +18 -18
- package/example/routes/user/user.route.js +0 -13
package/.prettierrc
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
{
|
|
2
|
-
"singleQuote": true,
|
|
3
|
-
"printWidth": 80,
|
|
4
|
-
"semi": true
|
|
1
|
+
{
|
|
2
|
+
"singleQuote": true,
|
|
3
|
+
"printWidth": 80,
|
|
4
|
+
"semi": true
|
|
5
5
|
}
|
package/database/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import mongo from './mongo.js';
|
|
2
|
-
|
|
3
|
-
const database = {
|
|
4
|
-
mongodb: mongo,
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export default database;
|
|
1
|
+
import mongo from './mongo.js';
|
|
2
|
+
|
|
3
|
+
const database = {
|
|
4
|
+
mongodb: mongo,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export default database;
|
package/database/mongo.js
CHANGED
|
@@ -1,14 +1,67 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { pathToFileURL } from 'node:url';
|
|
3
|
+
import TejLogger from 'tej-logger';
|
|
4
|
+
|
|
5
|
+
const packagePath = `${process.cwd()}/node_modules/mongoose/index.js`;
|
|
6
|
+
const logger = new TejLogger('Tejas CLI');
|
|
7
|
+
|
|
8
|
+
let mongoose = undefined;
|
|
9
|
+
|
|
10
|
+
const connect = async (uri, options, cb) => {
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
mongoose = await import(pathToFileURL(packagePath));
|
|
14
|
+
|
|
15
|
+
} catch (error) {
|
|
16
|
+
if (error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
17
|
+
await installMongoose('npm install mongoose');
|
|
18
|
+
mongoose = await import(pathToFileURL(packagePath));
|
|
19
|
+
|
|
20
|
+
} else {
|
|
21
|
+
cb(error);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
} finally {
|
|
25
|
+
mongoose.connect(uri, options).then(() => {
|
|
26
|
+
cb(undefined);
|
|
27
|
+
}).catch((error) => {
|
|
28
|
+
cb(error);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function installMongoose(command) {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const spinner = ['|', '/', '-', '\\'];
|
|
36
|
+
let current = 0;
|
|
37
|
+
|
|
38
|
+
// Start the spinner
|
|
39
|
+
const intervalId = setInterval(() => {
|
|
40
|
+
process.stdout.write(`\r${spinner[current]} Installing mongoose...`);
|
|
41
|
+
current = (current + 1) % spinner.length;
|
|
42
|
+
}, 100);
|
|
43
|
+
|
|
44
|
+
// Execute the command asynchronously to keep the spinner going
|
|
45
|
+
const child = spawn(command, { shell: true });
|
|
46
|
+
logger.info('Tejas will install mongoose to connect to mongodb...');
|
|
47
|
+
|
|
48
|
+
child.stderr.on('data', (data) => {
|
|
49
|
+
logger.error(`\n${data}`);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
child.on('close', (code) => {
|
|
53
|
+
process.stdout.write('\r');
|
|
54
|
+
clearInterval(intervalId);
|
|
55
|
+
if (code === 0) {
|
|
56
|
+
// Remove stdout of Installing mongodb...
|
|
57
|
+
logger.info('Mongoose installed successfully');
|
|
58
|
+
resolve();
|
|
59
|
+
} else {
|
|
60
|
+
logger.error('Mongoose installation failed');
|
|
61
|
+
reject();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default connect;
|
package/example/index.js
CHANGED
package/example/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Target } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
});
|
|
1
|
+
import { Target } from 'te.js';
|
|
2
|
+
import auth from '../middlewares/auth.js';
|
|
3
|
+
|
|
4
|
+
const target = new Target();
|
|
5
|
+
|
|
6
|
+
target.register('/hello', (ammo) => {
|
|
7
|
+
ammo.fire({
|
|
8
|
+
status: 200,
|
|
9
|
+
body: 'Hello, World!',
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Target, TejFileUploader } from 'te.js';
|
|
2
|
+
|
|
3
|
+
const target = new Target('/user');
|
|
4
|
+
|
|
5
|
+
const upload = new TejFileUploader({
|
|
6
|
+
destination: 'public/uploads',
|
|
7
|
+
maxFileSize: 5 * 1024 * 1024,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
target.register(
|
|
11
|
+
'/updateProfileImage',
|
|
12
|
+
upload.files('photos', 'covers'),
|
|
13
|
+
(ammo) => {
|
|
14
|
+
console.log(ammo.payload);
|
|
15
|
+
ammo.fire('Profile image updated successfully!')
|
|
16
|
+
},
|
|
17
|
+
);
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
"http_requests": true,
|
|
5
5
|
"exceptions": true
|
|
6
6
|
},
|
|
7
|
+
"dir":{
|
|
8
|
+
"targets": "targets"
|
|
9
|
+
},
|
|
7
10
|
"db": {
|
|
8
11
|
"type": "mongodb",
|
|
9
|
-
"uri": "mongodb://
|
|
12
|
+
"uri": "mongodb+srv://sheldon-cooper:J1T6P1rK4TYXCzUB@adb-cloaker.bhw9t.mongodb.net/retag-cloaker?retryWrites=true&w=majority"
|
|
10
13
|
}
|
|
11
|
-
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "te.js",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "A nodejs framework",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "te.js",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"start": "node te.js",
|
|
9
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
-
"prepare": "husky"
|
|
11
|
-
},
|
|
12
|
-
"author": "Hirak",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"devDependencies": {
|
|
15
|
-
"@types/node": "^20.12.5",
|
|
16
|
-
"husky": "^9.0.11",
|
|
17
|
-
"lint-staged": "^15.2.2",
|
|
18
|
-
"prettier": "3.2.5"
|
|
19
|
-
},
|
|
20
|
-
"repository": {
|
|
21
|
-
"type": "git",
|
|
22
|
-
"url": "git@github.com:hirakchhatbar/te.js.git"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"ansi-colors": "^4.1.3",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "te.js",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "A nodejs framework",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "te.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node te.js",
|
|
9
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
+
"prepare": "husky"
|
|
11
|
+
},
|
|
12
|
+
"author": "Hirak",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^20.12.5",
|
|
16
|
+
"husky": "^9.0.11",
|
|
17
|
+
"lint-staged": "^15.2.2",
|
|
18
|
+
"prettier": "3.2.5"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git@github.com:hirakchhatbar/te.js.git"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"ansi-colors": "^4.1.3",
|
|
26
|
+
"filesize": "^10.1.1",
|
|
27
|
+
"formidable": "^3.5.1",
|
|
28
|
+
"mime": "^4.0.1",
|
|
29
|
+
"statuses": "^2.0.1",
|
|
30
|
+
"tej-env": "^1.0.5",
|
|
31
|
+
"tej-logger": "^1.2.1"
|
|
32
|
+
},
|
|
33
|
+
"lint-staged": {
|
|
34
|
+
"**/*.{js,ts}": "prettier --write --ignore-unknown"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -1,51 +1,93 @@
|
|
|
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
|
-
|
|
1
|
+
async function parseDataBasedOnContentType(req) {
|
|
2
|
+
// Check if content type is JSON
|
|
3
|
+
if (req.headers['content-type'] === 'application/json') {
|
|
4
|
+
return await parseJSONRequestBody(req);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Check if content type is URL encoded
|
|
8
|
+
if (req.headers['content-type'] === 'application/x-www-form-urlencoded') {
|
|
9
|
+
return await parseUrlEncodedData(req);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Check if content type is multipart form data
|
|
13
|
+
if (req.headers['content-type']?.startsWith('multipart/form-data')) {
|
|
14
|
+
return await parseFormData(req);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function parseJSONRequestBody(req) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
let body = '';
|
|
23
|
+
req.on('data', (chunk) => {
|
|
24
|
+
body += chunk.toString();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
req.on('end', () => {
|
|
28
|
+
try {
|
|
29
|
+
const jsonData = JSON.parse(body);
|
|
30
|
+
resolve(jsonData); // Resolve promise with the parsed JSON
|
|
31
|
+
} catch (err) {
|
|
32
|
+
reject(new Error('Invalid JSON')); // Reject promise if JSON parsing fails
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseUrlEncodedData(req) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
let body = '';
|
|
41
|
+
|
|
42
|
+
req.on('data', (chunk) => {
|
|
43
|
+
body += chunk.toString();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
req.on('end', () => {
|
|
47
|
+
const data = new URLSearchParams(body);
|
|
48
|
+
const parsedData = Object.fromEntries(data);
|
|
49
|
+
resolve(parsedData);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseFormData(req) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
let body = '';
|
|
57
|
+
|
|
58
|
+
let files = [];
|
|
59
|
+
let fields = [];
|
|
60
|
+
|
|
61
|
+
req.on('data', (chunk) => {
|
|
62
|
+
body += chunk.toString();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
req.on('end', () => {
|
|
66
|
+
// Detect and parse multipart form data
|
|
67
|
+
if (req.headers['content-type'].startsWith('multipart/form-data')) {
|
|
68
|
+
const boundary =
|
|
69
|
+
'--' + req.headers['content-type'].split('boundary=')[1];
|
|
70
|
+
const parts = body
|
|
71
|
+
.split(boundary)
|
|
72
|
+
.filter((part) => part.trim() !== '' && part.trim() !== '--');
|
|
73
|
+
|
|
74
|
+
const parsedData = parts.map((part) => {
|
|
75
|
+
const partData = part.split('\r\n\r\n');
|
|
76
|
+
const headersPart = partData[0].trim().split('\r\n');
|
|
77
|
+
const valuePart = partData[1].trim();
|
|
78
|
+
let headers = {};
|
|
79
|
+
|
|
80
|
+
headersPart.forEach((header) => {
|
|
81
|
+
const [key, value] = header.split(': ');
|
|
82
|
+
headers[key.toLowerCase()] = value;
|
|
83
|
+
});
|
|
84
|
+
return { headers, value: valuePart };
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
resolve(parsedData);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default parseDataBasedOnContentType;
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import status from 'statuses';
|
|
2
|
-
|
|
3
|
-
const formattedData = (data) => {
|
|
4
|
-
if (typeof data === 'object') return JSON.stringify(data);
|
|
5
|
-
if (typeof data === 'string') return data;
|
|
6
|
-
if (typeof data === 'number') return status[data];
|
|
7
|
-
return data;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const statusAndData = (args) => {
|
|
11
|
-
if (!args || args.length === 0)
|
|
12
|
-
return {
|
|
13
|
-
statusCode: 204,
|
|
14
|
-
data: status(204),
|
|
15
|
-
contentType: 'text/plain',
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
if (args.length === 1 && typeof args[0] === 'number')
|
|
19
|
-
return {
|
|
20
|
-
statusCode: args[0],
|
|
21
|
-
data: status(args[0]),
|
|
22
|
-
contentType: 'text/plain',
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
let statusCode = 200;
|
|
26
|
-
let data = args[0];
|
|
27
|
-
if (args.length > 1) {
|
|
28
|
-
statusCode = args[0];
|
|
29
|
-
data = args[1];
|
|
30
|
-
if (!data) data = status[statusCode];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
statusCode,
|
|
35
|
-
data: formattedData(data),
|
|
36
|
-
contentType: contentType(data),
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const contentType = (data) => {
|
|
41
|
-
switch (typeof data) {
|
|
42
|
-
case 'object':
|
|
43
|
-
return 'application/json';
|
|
44
|
-
case 'string':
|
|
45
|
-
return 'text/html';
|
|
46
|
-
case 'number':
|
|
47
|
-
return 'text/plain';
|
|
48
|
-
default:
|
|
49
|
-
return 'text/plain';
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export { statusAndData, contentType };
|
|
1
|
+
import status from 'statuses';
|
|
2
|
+
|
|
3
|
+
const formattedData = (data) => {
|
|
4
|
+
if (typeof data === 'object') return JSON.stringify(data);
|
|
5
|
+
if (typeof data === 'string') return data;
|
|
6
|
+
if (typeof data === 'number') return status[data];
|
|
7
|
+
return data;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const statusAndData = (args) => {
|
|
11
|
+
if (!args || args.length === 0)
|
|
12
|
+
return {
|
|
13
|
+
statusCode: 204,
|
|
14
|
+
data: status(204),
|
|
15
|
+
contentType: 'text/plain',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
if (args.length === 1 && typeof args[0] === 'number')
|
|
19
|
+
return {
|
|
20
|
+
statusCode: args[0],
|
|
21
|
+
data: status(args[0]),
|
|
22
|
+
contentType: 'text/plain',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
let statusCode = 200;
|
|
26
|
+
let data = args[0];
|
|
27
|
+
if (args.length > 1) {
|
|
28
|
+
statusCode = args[0];
|
|
29
|
+
data = args[1];
|
|
30
|
+
if (!data) data = status[statusCode];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
statusCode,
|
|
35
|
+
data: formattedData(data),
|
|
36
|
+
contentType: contentType(data),
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const contentType = (data) => {
|
|
41
|
+
switch (typeof data) {
|
|
42
|
+
case 'object':
|
|
43
|
+
return 'application/json';
|
|
44
|
+
case 'string':
|
|
45
|
+
return 'text/html';
|
|
46
|
+
case 'number':
|
|
47
|
+
return 'text/plain';
|
|
48
|
+
default:
|
|
49
|
+
return 'text/plain';
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export { statusAndData, contentType };
|
package/server/ammo/enhancer.js
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
import bodyParser from './body-parser.js';
|
|
2
|
-
|
|
3
|
-
function hostname(req) {
|
|
4
|
-
let host = req.headers['X-Forwarded-Host'];
|
|
5
|
-
|
|
6
|
-
if (!host) {
|
|
7
|
-
host = req.headers.host;
|
|
8
|
-
} else if (host.indexOf(',') !== -1) {
|
|
9
|
-
host = host.substring(0, host.indexOf(',')).trimRight();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
return host;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function generatePayload(req) {
|
|
16
|
-
const obj = {};
|
|
17
|
-
|
|
18
|
-
const searchParams = new URLSearchParams(req.url.split('?')[1]);
|
|
19
|
-
for (const [key, value] of searchParams) {
|
|
20
|
-
obj[key] = value;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const body = await bodyParser(req);
|
|
24
|
-
if (body) Object.assign(obj, body);
|
|
25
|
-
return obj;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function protocol(req) {
|
|
29
|
-
const proto = req.connection.encrypted ? 'https' : 'http';
|
|
30
|
-
|
|
31
|
-
const header = req.headers['X-Forwarded-Proto'] || proto;
|
|
32
|
-
const index = header.indexOf(',');
|
|
33
|
-
|
|
34
|
-
return index !== -1 ? header.substring(0, index).trim() : header.trim();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const enhance = async (ammo) => {
|
|
38
|
-
const req = ammo.req;
|
|
39
|
-
|
|
40
|
-
ammo.ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
|
41
|
-
ammo.headers = req.headers;
|
|
42
|
-
ammo.payload = await generatePayload(req);
|
|
43
|
-
ammo.method = req.method;
|
|
44
|
-
|
|
45
|
-
ammo.protocol = protocol(req);
|
|
46
|
-
ammo.hostname = hostname(req);
|
|
47
|
-
ammo.path = req.url;
|
|
48
|
-
ammo.endpoint = req.url.split('?')[0];
|
|
49
|
-
|
|
50
|
-
ammo.fullURL = `${ammo.protocol}://${ammo.hostname}/${ammo.path}`;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export default enhance;
|
|
1
|
+
import bodyParser from './body-parser.js';
|
|
2
|
+
|
|
3
|
+
function hostname(req) {
|
|
4
|
+
let host = req.headers['X-Forwarded-Host'];
|
|
5
|
+
|
|
6
|
+
if (!host) {
|
|
7
|
+
host = req.headers.host;
|
|
8
|
+
} else if (host.indexOf(',') !== -1) {
|
|
9
|
+
host = host.substring(0, host.indexOf(',')).trimRight();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return host;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function generatePayload(req) {
|
|
16
|
+
const obj = {};
|
|
17
|
+
|
|
18
|
+
const searchParams = new URLSearchParams(req.url.split('?')[1]);
|
|
19
|
+
for (const [key, value] of searchParams) {
|
|
20
|
+
obj[key] = value;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const body = await bodyParser(req);
|
|
24
|
+
if (body) Object.assign(obj, body);
|
|
25
|
+
return obj;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function protocol(req) {
|
|
29
|
+
const proto = req.connection.encrypted ? 'https' : 'http';
|
|
30
|
+
|
|
31
|
+
const header = req.headers['X-Forwarded-Proto'] || proto;
|
|
32
|
+
const index = header.indexOf(',');
|
|
33
|
+
|
|
34
|
+
return index !== -1 ? header.substring(0, index).trim() : header.trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const enhance = async (ammo) => {
|
|
38
|
+
const req = ammo.req;
|
|
39
|
+
|
|
40
|
+
ammo.ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
|
|
41
|
+
ammo.headers = req.headers;
|
|
42
|
+
ammo.payload = await generatePayload(req);
|
|
43
|
+
ammo.method = req.method;
|
|
44
|
+
|
|
45
|
+
ammo.protocol = protocol(req);
|
|
46
|
+
ammo.hostname = hostname(req);
|
|
47
|
+
ammo.path = req.url;
|
|
48
|
+
ammo.endpoint = req.url.split('?')[0];
|
|
49
|
+
|
|
50
|
+
ammo.fullURL = `${ammo.protocol}://${ammo.hostname}/${ammo.path}`;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default enhance;
|