nodester 0.0.1 → 0.0.6
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 +61 -26
- package/lib/application/index.js +86 -35
- package/lib/constants/Operations.js +23 -0
- package/lib/controllers/methods/index.js +170 -0
- package/lib/controllers/mixins/index.js +213 -0
- package/lib/enums/Enum.js +16 -0
- package/lib/factories/errors/CustomError.js +7 -5
- package/lib/factories/responses/html.js +7 -2
- package/lib/factories/responses/rest.js +110 -0
- package/lib/http/codes/index.js +157 -0
- package/lib/{application/http → http}/request.js +6 -30
- package/lib/{application/http → http}/response.js +20 -53
- package/lib/middlewares/etag/index.js +62 -0
- package/lib/middlewares/ql/sequelize/index.js +34 -0
- package/lib/middlewares/ql/sequelize/interpreter/ModelsTree.js +121 -0
- package/lib/middlewares/ql/sequelize/interpreter/QueryLexer.js +456 -0
- package/lib/models/define.js +6 -13
- package/lib/models/mixins.js +28 -15
- package/lib/params/Params.js +34 -0
- package/lib/queries/NodesterQueryParams.js +139 -0
- package/lib/router/handlers.util.js +61 -0
- package/lib/router/index.js +386 -0
- package/lib/router/route.js +124 -0
- package/lib/router/routes.util.js +66 -0
- package/lib/stacks/MarkersStack.js +35 -0
- package/lib/{application → stacks}/MiddlewareStack.js +47 -13
- package/lib/utils/path.util.js +3 -1
- package/lib/utils/types.util.js +51 -1
- package/lib/validators/dates.js +25 -0
- package/lib/validators/numbers.js +14 -0
- package/package.json +16 -2
- package/tests/index.test.js +7 -2
- package/tests/nql.test.js +277 -0
- package/docs/App.md +0 -13
- package/docs/Queries.md +0 -61
- package/docs/Readme.md +0 -2
- package/docs/Routing.md +0 -34
- package/examples/goal/index.js +0 -23
- package/examples/rest/index.js +0 -25
- package/examples/rest/node_modules/.package-lock.json +0 -40
- package/examples/rest/package-lock.json +0 -72
- package/examples/rest/package.json +0 -14
- package/lib/constants/ConstantsEnum.js +0 -13
- package/lib/factories/responses/api.js +0 -90
- package/lib/routers/Default/index.js +0 -143
- package/lib/routers/Default/layer.js +0 -50
- package/lib/routers/Main/index.js +0 -10
- package/lib/routers/Roles/index.js +0 -81
- package/lib/utils/params.util.js +0 -19
- /package/lib/{controllers/Controller.js → _/n_controllers/Controller.js"} +0 -0
- /package/lib/{controllers/JWTController.js → _/n_controllers/JWTController.js"} +0 -0
- /package/lib/{controllers/ServiceController.js → _/n_controllers/ServiceController.js"} +0 -0
- /package/lib/{controllers/WebController.js → _/n_controllers/WebController.js"} +0 -0
- /package/lib/{facades → _facades}/Facade.js +0 -0
- /package/lib/{facades → _facades}/FacadeParams.js +0 -0
- /package/lib/{facades → _facades}/ServiceFacade.js +0 -0
- /package/lib/{facades → _facades}/jwt.facade.js +0 -0
- /package/lib/{application/http → http}/utils.js +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const {
|
|
2
|
+
getOne,
|
|
3
|
+
getMany,
|
|
4
|
+
createOne,
|
|
5
|
+
updateOne,
|
|
6
|
+
deleteOne
|
|
7
|
+
} = require('../methods');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
withDefaultCRUD: _withDefaultCRUD,
|
|
12
|
+
withDefaultErrorProcessing: _withDefaultErrorProcessing,
|
|
13
|
+
setMethod: _setMethod
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Sets one of or all of CRUD methods to Controller.
|
|
19
|
+
*
|
|
20
|
+
* @param {Function|Object} controller
|
|
21
|
+
* @param {Object} opts
|
|
22
|
+
* - @param {Function|Object} facade
|
|
23
|
+
* - @param {String} name
|
|
24
|
+
* - @param {Array} only
|
|
25
|
+
*
|
|
26
|
+
* @return {Function|Object} controller
|
|
27
|
+
*
|
|
28
|
+
* @api public
|
|
29
|
+
* @alias withDefaultCRUD
|
|
30
|
+
*/
|
|
31
|
+
function _withDefaultCRUD(controller, opts={}) {
|
|
32
|
+
const {
|
|
33
|
+
facade,
|
|
34
|
+
|
|
35
|
+
// Optional:
|
|
36
|
+
name,
|
|
37
|
+
only
|
|
38
|
+
} = opts;
|
|
39
|
+
|
|
40
|
+
if (!controller) {
|
|
41
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!facade) {
|
|
46
|
+
const err = new TypeError(`'opts.facade' argument is invalid.`);
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Set main facade:
|
|
51
|
+
if (facade.constructor.name === 'Function') {
|
|
52
|
+
controller.facade = new facade();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
controller.facade = facade;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Set model info:
|
|
59
|
+
const model = facade.model;
|
|
60
|
+
// Extract plural name of this model.
|
|
61
|
+
const modelPluralName = model?.options?.name?.plural;
|
|
62
|
+
// Set name of this controller:
|
|
63
|
+
Object.defineProperty(controller, 'name', {
|
|
64
|
+
value: name ?? `${ modelPluralName ?? controller.name }Controller`,
|
|
65
|
+
writable: false
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
// If only certain methods should be set:
|
|
70
|
+
if (!!only) {
|
|
71
|
+
for (const selectedMethod of only) {
|
|
72
|
+
switch(selectedMethod) {
|
|
73
|
+
case 'getOne':
|
|
74
|
+
controller.getOne = getOne.bind(controller);
|
|
75
|
+
break;
|
|
76
|
+
case 'getMany':
|
|
77
|
+
controller.getMany = getMany.bind(controller);
|
|
78
|
+
break;
|
|
79
|
+
case 'createOne':
|
|
80
|
+
controller.createOne = createOne.bind(controller);
|
|
81
|
+
break;
|
|
82
|
+
case 'updateOne':
|
|
83
|
+
controller.updateOne = updateOne.bind(controller);
|
|
84
|
+
break;
|
|
85
|
+
case 'deleteOne':
|
|
86
|
+
controller.deleteOne = deleteOne.bind(controller);
|
|
87
|
+
break;
|
|
88
|
+
|
|
89
|
+
default:
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Or set all methods:
|
|
95
|
+
else {
|
|
96
|
+
controller.getOne = getOne.bind(controller);
|
|
97
|
+
controller.getMany = getMany.bind(controller);
|
|
98
|
+
controller.createOne = createOne.bind(controller);
|
|
99
|
+
controller.updateOne = updateOne.bind(controller);
|
|
100
|
+
controller.deleteOne = deleteOne.bind(controller);
|
|
101
|
+
|
|
102
|
+
// Set empty hooks:
|
|
103
|
+
controller.afterGetOne = async () => {};
|
|
104
|
+
controller.afterGetMany = async () => {};
|
|
105
|
+
controller.afterCreateOne = async () => {};
|
|
106
|
+
controller.afterUpdateOne = async () => {};
|
|
107
|
+
controller.afterDeleteOe = async () => {};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// TODO: remove.
|
|
111
|
+
controller.respondOk = (res, data) => res.json(data);
|
|
112
|
+
controller.respondNotOk = (res, data) => { res.status(data.status); res.json(data); };
|
|
113
|
+
|
|
114
|
+
return controller;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sets default error responses to Controller.
|
|
120
|
+
*
|
|
121
|
+
* @param {Function|Object} controller
|
|
122
|
+
* @param {Object} opts
|
|
123
|
+
*
|
|
124
|
+
* @return {Function|Object} controller
|
|
125
|
+
*
|
|
126
|
+
* @api public
|
|
127
|
+
* @alias withDefaultErrorProcessing
|
|
128
|
+
*/
|
|
129
|
+
function _withDefaultErrorProcessing(controller, opts={}) {
|
|
130
|
+
if (!controller) {
|
|
131
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Set processError:
|
|
136
|
+
controller.processError = function (error, req, res) {
|
|
137
|
+
// Default error message.
|
|
138
|
+
let errorMessage = error?.message ?? 'Internal server error';
|
|
139
|
+
// Default HTTP status code.
|
|
140
|
+
let statusCode = error?.status ?? error?.statusCode ?? 500;
|
|
141
|
+
// Error response object.
|
|
142
|
+
let errorResponse = {};
|
|
143
|
+
|
|
144
|
+
switch(error.name) {
|
|
145
|
+
case('Unauthorized'): {
|
|
146
|
+
statusCode = 401;
|
|
147
|
+
errorResponse.details = { message: 'Unauthorized' };
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case('NotFound'): {
|
|
151
|
+
statusCode = 404;
|
|
152
|
+
errorResponse.details = { message: errorMessage };
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case('ValidationError'): {
|
|
156
|
+
statusCode = 406;
|
|
157
|
+
errorResponse.details = error?.details;
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case('ConflictError'): {
|
|
161
|
+
statusCode = 409;
|
|
162
|
+
errorResponse.details = error?.details ?? error?.message;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case('SequelizeUniqueConstraintError'): {
|
|
166
|
+
statusCode = 409;
|
|
167
|
+
errorResponse.details = error?.errors;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
case('InternalValidationError'): {
|
|
171
|
+
statusCode = 500;
|
|
172
|
+
errorResponse.details = { message:'Error' };
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
default: {
|
|
176
|
+
errorResponse.details = { message:errorMessage };
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Send error response with provided status code.
|
|
182
|
+
return this.respondNotOk(res, {
|
|
183
|
+
error: {
|
|
184
|
+
...errorResponse,
|
|
185
|
+
code: statusCode
|
|
186
|
+
},
|
|
187
|
+
status: statusCode
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return controller;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Sets one of CRUD methods to Controller.
|
|
197
|
+
*
|
|
198
|
+
* @param {Function|Object} controller
|
|
199
|
+
* @param {Object} opts
|
|
200
|
+
*
|
|
201
|
+
* @return {Function|Object} controller
|
|
202
|
+
*
|
|
203
|
+
* @api public
|
|
204
|
+
* @alias withDefaultCRUD
|
|
205
|
+
*/
|
|
206
|
+
function _setMethod(controller,) {
|
|
207
|
+
if (!controller) {
|
|
208
|
+
const err = new TypeError(`'controller' argument is not provided.`);
|
|
209
|
+
throw err;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
module.exports = Enum;
|
|
3
|
+
|
|
4
|
+
function Enum(constantsList = {}, writable=false) {
|
|
5
|
+
const def = (key, value) => Object.defineProperty(this, key, { value, writable: !!writable });
|
|
6
|
+
|
|
7
|
+
// Set list.
|
|
8
|
+
def('list', constantsList);
|
|
9
|
+
|
|
10
|
+
// Set getters:
|
|
11
|
+
Object.keys(constantsList)
|
|
12
|
+
.forEach(key => def(key, constantsList[key]) );
|
|
13
|
+
|
|
14
|
+
// Set constants in static array.
|
|
15
|
+
def('asArray', Object.values(constantsList) );
|
|
16
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
module.exports = class CustomError extends Error {
|
|
2
3
|
constructor(message) {
|
|
3
4
|
super(message);
|
|
5
|
+
|
|
4
6
|
this.name = this.constructor.name;
|
|
5
7
|
this.status = 500;
|
|
6
8
|
|
|
@@ -14,9 +16,9 @@ class CustomError extends Error {
|
|
|
14
16
|
this.status = originalError?.status ?? this.status;
|
|
15
17
|
|
|
16
18
|
// Append stack from original error.
|
|
17
|
-
const
|
|
18
|
-
this.stack = this.stack.split('\n')
|
|
19
|
+
const linesCount = (this.message.match(/\n/g)||[]).length + 1;
|
|
20
|
+
this.stack = this.stack.split('\n')
|
|
21
|
+
.slice(0, linesCount+1)
|
|
22
|
+
.join('\n') + '\n' + originalError.stack;
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
|
-
|
|
22
|
-
module.exports = CustomError;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* WARNING: Unfinihsed. Do not use!
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
2
5
|
|
|
6
|
+
const Params = require('../../params/Params');
|
|
3
7
|
|
|
4
|
-
|
|
8
|
+
|
|
9
|
+
module.exports = class HtmlResponseFactory {
|
|
5
10
|
constructor() {}
|
|
6
11
|
|
|
7
12
|
/**
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Rest response factory.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const ResponseFormats = require('../../constants/ResponseFormats');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
createGenericResponse: _createGenericResponse,
|
|
10
|
+
createOKResponse: _createOKResponse,
|
|
11
|
+
createErrorResponse: _createErrorResponse,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
* Format for all API responses will be JSON
|
|
17
|
+
* {
|
|
18
|
+
* content: {...}
|
|
19
|
+
* error: {...}
|
|
20
|
+
* }
|
|
21
|
+
* Status code is sent in header.
|
|
22
|
+
*
|
|
23
|
+
* If error is not present, error should be null.
|
|
24
|
+
* If error is present, content can be null (But it's not required).
|
|
25
|
+
*
|
|
26
|
+
* @param {ServerResponse} res
|
|
27
|
+
* @param {Object} options
|
|
28
|
+
*
|
|
29
|
+
* @alias createGenericResponse
|
|
30
|
+
* @api public
|
|
31
|
+
*/
|
|
32
|
+
function _createGenericResponse(
|
|
33
|
+
res,
|
|
34
|
+
options = {
|
|
35
|
+
status: 200,
|
|
36
|
+
content: {},
|
|
37
|
+
error: null,
|
|
38
|
+
format: ResponseFormats.JSON
|
|
39
|
+
}
|
|
40
|
+
) {
|
|
41
|
+
try {
|
|
42
|
+
const data = {
|
|
43
|
+
content: options?.content ?? null,
|
|
44
|
+
error: options?.error ?? null
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
switch(options?.format) {
|
|
48
|
+
case ResponseFormats.JSON:
|
|
49
|
+
return options?.res.status(options?.status).json(data);
|
|
50
|
+
case ResponseFormats.XML:
|
|
51
|
+
// TODO: format data into XML.
|
|
52
|
+
return options?.res.status(options?.status).send(data);
|
|
53
|
+
break;
|
|
54
|
+
default: {
|
|
55
|
+
const err = new TypeError("No format specified.");
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch(error) {
|
|
61
|
+
const err = new Error(`Could not create generic response: ${error.message}`);
|
|
62
|
+
err.name = error?.name;
|
|
63
|
+
err.code = error?.code;
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Sends response with status code 200.
|
|
71
|
+
* Should be called on all successful respones.
|
|
72
|
+
*
|
|
73
|
+
* @param {ServerResponse} res
|
|
74
|
+
* @param <Object> content
|
|
75
|
+
* @param <String> format
|
|
76
|
+
*
|
|
77
|
+
* @alias createOKResponse
|
|
78
|
+
* @api public
|
|
79
|
+
*/
|
|
80
|
+
function _createOKResponse(res, options={}) {
|
|
81
|
+
|
|
82
|
+
return this.createGenericResponse(res, {
|
|
83
|
+
...options,
|
|
84
|
+
status: 200,
|
|
85
|
+
format: options?.format ?? ResponseFormats.JSON
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Sends response with provided error code.
|
|
92
|
+
* Should be called on all failed respones.
|
|
93
|
+
*
|
|
94
|
+
* @param {ServerResponse} res
|
|
95
|
+
* @param <Object> error
|
|
96
|
+
* @param <Object> content (optional)
|
|
97
|
+
* @param <Int> status
|
|
98
|
+
* @param <String> format
|
|
99
|
+
*
|
|
100
|
+
* @alias createErrorResponse
|
|
101
|
+
* @api public
|
|
102
|
+
*/
|
|
103
|
+
function _createErrorResponse(res, options) {
|
|
104
|
+
|
|
105
|
+
return this.createGenericResponse(res, {
|
|
106
|
+
...options,
|
|
107
|
+
status: options?.status ?? 500,
|
|
108
|
+
format: options?.format ?? ResponseFormats.JSON
|
|
109
|
+
});
|
|
110
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
const symbolsByTag = {
|
|
2
|
+
// Informational:
|
|
3
|
+
CONTINUE: Symbol('100: Continue'),
|
|
4
|
+
SWITCHING_PROTOCOLS: Symbol('101: Switching Protocols'),
|
|
5
|
+
PROCESSING: Symbol('102: Processing'),
|
|
6
|
+
EARLY_HINTS: Symbol('103: Early Hints'),
|
|
7
|
+
|
|
8
|
+
// Success:
|
|
9
|
+
OK: Symbol('200: OK'),
|
|
10
|
+
CREATED: Symbol('201: Created'),
|
|
11
|
+
ACCEPTED: Symbol('202: Accepted'),
|
|
12
|
+
NON_AUTHORITATIVE_INFORMATION: Symbol('203: Non-Authoritative Information'),
|
|
13
|
+
NO_CONTENT: Symbol('204: No Content'),
|
|
14
|
+
RESET_CONTENT: Symbol('205: Reset Content'),
|
|
15
|
+
PARTIAL_CONTENT: Symbol('206: Partial Content'),
|
|
16
|
+
MULTI_STATUS: Symbol('207: Multi-Status'),
|
|
17
|
+
ALREADY_REPORTED: Symbol('208: Already Reported'),
|
|
18
|
+
IM_USED: Symbol('226: IM Used'),
|
|
19
|
+
|
|
20
|
+
// Redirections:
|
|
21
|
+
MULTIPLE_CHOICES: Symbol('300: Multiple Choices'),
|
|
22
|
+
MOVED_PERMANENTLY: Symbol('301: Moved Permanently'),
|
|
23
|
+
FOUND: Symbol('302: Found'),
|
|
24
|
+
SEE_OTHER: Symbol('303: See Other'),
|
|
25
|
+
NOT_MODIFIED: Symbol('304: Not Modified'),
|
|
26
|
+
USE_PROXY: Symbol('305: Use Proxy'),
|
|
27
|
+
TEMPORARY_REDIRECT: Symbol('307: Temporary Redirect'),
|
|
28
|
+
PERMANENT_REDIRECT: Symbol('308: Permanent Redirect'),
|
|
29
|
+
|
|
30
|
+
// Client Errors:
|
|
31
|
+
BAD_REQUEST: Symbol('400: Bad Request'),
|
|
32
|
+
UNAUTHORIZED: Symbol('401: Unauthorized'),
|
|
33
|
+
PAYMENT_REQUIRED: Symbol('402: Payment Required'),
|
|
34
|
+
FORBIDDEN: Symbol('403: Forbidden'),
|
|
35
|
+
NOT_FOUND: Symbol('404: Not Found'),
|
|
36
|
+
METHOD_NOT_ALLOWED: Symbol('405: Method Not Allowed'),
|
|
37
|
+
NOT_ACCEPTABLE: Symbol('406: Not Acceptable'),
|
|
38
|
+
PROXY_AUTHENTICATION_REQUIRED: Symbol('407: Proxy Authentication Required'),
|
|
39
|
+
REQUEST_TIMEOUT: Symbol('408: Request Timeout'),
|
|
40
|
+
CONFLICT: Symbol('409: Conflict'),
|
|
41
|
+
GONE: Symbol('410: Gone'),
|
|
42
|
+
LENGTH_REQUIRED: Symbol('411: Length Required'),
|
|
43
|
+
PRECONDITION_FAILED: Symbol('412: Precondition Failed'),
|
|
44
|
+
PAYLOAD_TOO_LARGE: Symbol('413: Payload Too Large'),
|
|
45
|
+
URI_TOO_LONG: Symbol('414: URI Too Long'),
|
|
46
|
+
UNSUPPORTED_MEDIA_TYPE: Symbol('415: Unsupported Media Type'),
|
|
47
|
+
RANGE_NOT_SATISFIABLE: Symbol('416: Range Not Satisfiable'),
|
|
48
|
+
EXPECTATION_FAILED: Symbol('417: Expectation Failed'),
|
|
49
|
+
IM_A_TEAPOT: Symbol("418: I'm a teapot"),
|
|
50
|
+
MISDIRECTED_REQUEST: Symbol('421: Misdirected Request'),
|
|
51
|
+
UNPROCESSABLE_ENTITY: Symbol('422: Unprocessable Entity'),
|
|
52
|
+
LOCKED: Symbol('423: Locked'),
|
|
53
|
+
FAILED_DEPENDENCY: Symbol('424: Failed Dependency'),
|
|
54
|
+
TOO_EARLY: Symbol('425: Too Early'),
|
|
55
|
+
UPGRADE_REQUIRED: Symbol('426: Upgrade Required'),
|
|
56
|
+
PRECONDITION_REQUIRED: Symbol('428: Precondition Required'),
|
|
57
|
+
TOO_MANY_REQUESTS: Symbol('429: Too Many Requests'),
|
|
58
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE: Symbol('431: Request Header Fields Too Large'),
|
|
59
|
+
UNAVAILABLE_FOR_LEGAL_REASONS: Symbol('451: Unavailable For Legal Reasons'),
|
|
60
|
+
|
|
61
|
+
// Server Errors:
|
|
62
|
+
INTERNAL_SERVER_ERROR: Symbol('500: Internal Server Error'),
|
|
63
|
+
NOT_IMPLEMENTED: Symbol('501: Not Implemented'),
|
|
64
|
+
BAD_GATEWAY: Symbol('502: Bad Gateway'),
|
|
65
|
+
SERVICE_UNAVAILABLE: Symbol('503: Service Unavailable'),
|
|
66
|
+
GATEWAY_TIMEOUT: Symbol('504: Gateway Timeout'),
|
|
67
|
+
HTTP_VERSION_NOT_SUPPORTED: Symbol('505: HTTP Version Not Supported'),
|
|
68
|
+
VARIANT_ALSO_NEGOTIATES: Symbol('506: Variant Also Negotiates'),
|
|
69
|
+
INSUFFICIENT_STORAGE: Symbol('507: Insufficient Storage'),
|
|
70
|
+
LOOP_DETECTED: Symbol('508: Loop Detected'),
|
|
71
|
+
NOT_EXTENDED: Symbol('510: Not Extended'),
|
|
72
|
+
NETWORK_AUTHENTICATION_REQUIRED: Symbol('511: Network Authentication Required')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const descriptionsByCode = {
|
|
76
|
+
// Informational:
|
|
77
|
+
100: 'Continue',
|
|
78
|
+
101: 'Switching Protocols',
|
|
79
|
+
102: 'Processing',
|
|
80
|
+
103: 'Early Hints',
|
|
81
|
+
|
|
82
|
+
// Success:
|
|
83
|
+
200: 'OK',
|
|
84
|
+
201: 'Created',
|
|
85
|
+
202: 'Accepted',
|
|
86
|
+
203: 'Non-Authoritative Information',
|
|
87
|
+
204: 'No Content',
|
|
88
|
+
205: 'Reset Content',
|
|
89
|
+
206: 'Partial Content',
|
|
90
|
+
207: 'Multi-Status',
|
|
91
|
+
208: 'Already Reported',
|
|
92
|
+
226: 'IM Used',
|
|
93
|
+
|
|
94
|
+
// Redirections:
|
|
95
|
+
300: 'Multiple Choices',
|
|
96
|
+
301: 'Moved Permanently',
|
|
97
|
+
302: 'Found',
|
|
98
|
+
303: 'See Other',
|
|
99
|
+
304: 'Not Modified',
|
|
100
|
+
305: 'Use Proxy',
|
|
101
|
+
307: 'Temporary Redirect',
|
|
102
|
+
308: 'Permanent Redirect',
|
|
103
|
+
|
|
104
|
+
// Client Errors:
|
|
105
|
+
400: 'Bad Request',
|
|
106
|
+
401: 'Unauthorized',
|
|
107
|
+
402: 'Payment Required',
|
|
108
|
+
403: 'Forbidden',
|
|
109
|
+
404: 'Not Found',
|
|
110
|
+
405: 'Method Not Allowed',
|
|
111
|
+
406: 'Not Acceptable',
|
|
112
|
+
407: 'Proxy Authentication Required',
|
|
113
|
+
408: 'Request Timeout',
|
|
114
|
+
409: 'Conflict',
|
|
115
|
+
410: 'Gone',
|
|
116
|
+
411: 'Length Required',
|
|
117
|
+
412: 'Precondition Failed',
|
|
118
|
+
413: 'Payload Too Large',
|
|
119
|
+
414: 'URI Too Long',
|
|
120
|
+
415: 'Unsupported Media Type',
|
|
121
|
+
416: 'Range Not Satisfiable',
|
|
122
|
+
417: 'Expectation Failed',
|
|
123
|
+
418: 'I\'m a teapot',
|
|
124
|
+
421: 'Misdirected Request',
|
|
125
|
+
422: 'Unprocessable Entity',
|
|
126
|
+
423: 'Locked',
|
|
127
|
+
424: 'Failed Dependency',
|
|
128
|
+
425: 'Too Early',
|
|
129
|
+
426: 'Upgrade Required',
|
|
130
|
+
428: 'Precondition Required',
|
|
131
|
+
429: 'Too Many Requests',
|
|
132
|
+
431: 'Request Header Fields Too Large',
|
|
133
|
+
451: 'Unavailable For Legal Reasons',
|
|
134
|
+
|
|
135
|
+
// Server Errors:
|
|
136
|
+
500: 'Internal Server Error',
|
|
137
|
+
501: 'Not Implemented',
|
|
138
|
+
502: 'Bad Gateway',
|
|
139
|
+
503: 'Service Unavailable',
|
|
140
|
+
504: 'Gateway Timeout',
|
|
141
|
+
505: 'HTTP Version Not Supported',
|
|
142
|
+
506: 'Variant Also Negotiates',
|
|
143
|
+
507: 'Insufficient Storage',
|
|
144
|
+
508: 'Loop Detected',
|
|
145
|
+
510: 'Not Extended',
|
|
146
|
+
511: 'Network Authentication Required'
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
descriptions: {
|
|
151
|
+
byCode: descriptionsByCode
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
symbols: {
|
|
155
|
+
byTag: symbolsByTag
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -7,14 +7,14 @@
|
|
|
7
7
|
const accepts = require('accepts');
|
|
8
8
|
const isIP = require('net').isIP;
|
|
9
9
|
const typeis = require('type-is');
|
|
10
|
-
const
|
|
10
|
+
const { IncomingMessage } = require('http');
|
|
11
11
|
const fresh = require('fresh');
|
|
12
12
|
const parseRange = require('range-parser');
|
|
13
13
|
const parse = require('parseurl');
|
|
14
14
|
const proxyaddr = require('proxy-addr');
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
const req =
|
|
17
|
+
const req = IncomingMessage.prototype;
|
|
18
18
|
|
|
19
19
|
module.exports = req;
|
|
20
20
|
|
|
@@ -355,39 +355,15 @@ defineGetter(req, 'path', function path() {
|
|
|
355
355
|
|
|
356
356
|
/**
|
|
357
357
|
* Parse the "Host" header field to a hostname.
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
* address, the "X-Forwarded-Host" header field will
|
|
361
|
-
* be trusted.
|
|
358
|
+
* Will return "X-Forwarded-Host" if set,
|
|
359
|
+
* or "Host" as a fallback.
|
|
362
360
|
*
|
|
363
361
|
* @return {String}
|
|
364
362
|
* @public
|
|
365
363
|
*/
|
|
366
364
|
defineGetter(req, 'hostname', function hostname() {
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if (!host || !trust(this.connection.remoteAddress, 0)) {
|
|
371
|
-
host = this.get('Host');
|
|
372
|
-
}
|
|
373
|
-
else if (host.indexOf(',') !== -1) {
|
|
374
|
-
// Note: X-Forwarded-Host is normally only ever a
|
|
375
|
-
// single value, but this is to be safe.
|
|
376
|
-
host = host.substring(0, host.indexOf(',')).trimRight()
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (!host)
|
|
380
|
-
return;
|
|
381
|
-
|
|
382
|
-
// IPv6 literal support
|
|
383
|
-
const offset = host[0] === '['
|
|
384
|
-
? host.indexOf(']') + 1
|
|
385
|
-
: 0;
|
|
386
|
-
const index = host.indexOf(':', offset);
|
|
387
|
-
|
|
388
|
-
return index !== -1
|
|
389
|
-
? host.substring(0, index)
|
|
390
|
-
: host;
|
|
365
|
+
const host = this.get('X-Forwarded-Host') ?? this.get('Host');
|
|
366
|
+
return host;
|
|
391
367
|
});
|
|
392
368
|
|
|
393
369
|
|