slower 1.1.12 → 1.1.15

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/lib/router.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const http = require('http');
2
2
  const fs = require('fs');
3
- const { noop, slugify, isSparseEqual, last, renderDynamicHTML, setSocketLocals, setSocketSecurityHeaders } = require('./utils');
3
+ const { clone, noop, slugify, isSparseEqual, last, renderDynamicHTML, setSocketLocals, setSocketSecurityHeaders } = require('./utils');
4
4
 
5
5
  class Route {
6
6
  constructor (path, type, callback) {
@@ -37,7 +37,7 @@ class SlowerRouter {
37
37
  this.routes = [];
38
38
  this.middleware = [noop];
39
39
  this.fallback = noop;
40
- this.allowedMethods = [];
40
+ this.allowedMethods = clone(SlowerRouter.http_methods);
41
41
  this.blockedMethodCallback = noop;
42
42
  }
43
43
 
@@ -72,7 +72,7 @@ class SlowerRouter {
72
72
  setRoute = function (path = '/', type = 'GET', callback) {
73
73
  let stat = new Route(path, type, callback);
74
74
  this.routes.push(stat);
75
- return stat;
75
+ return this;
76
76
  }
77
77
 
78
78
  /**
@@ -82,13 +82,10 @@ class SlowerRouter {
82
82
  * @returns {Array} The used middlewares list
83
83
  */
84
84
  setMiddleware = function (callback) {
85
- return this.middleware.push((typeof callback == 'function' ? callback : noop));
85
+ this.middleware.push((typeof callback == 'function' ? callback : noop));
86
+ return this;
86
87
  }
87
88
 
88
- // SERVES FILES FOR SPECIFIC PATHS. WILDCARS ALLOWED. BE CAREFUL - PATH TRAVERSAL MAY BE POSSIBLE
89
- // Use app.setStatic('/*', __dirname+'/') for serving all local files.
90
- // or use app.setStatic('/*', __dirname+'/public/') for serving files in a specific folder (public).
91
- // This is a one-liner for the setRoute function, when the route responds with a simple page or document
92
89
  /**
93
90
  * Defines a route for a determined request method
94
91
  * @category Router
@@ -97,8 +94,6 @@ class SlowerRouter {
97
94
  * @param {String} mime The file's mime type
98
95
  * @param {Object} replacementData The replacement data map for the dynamic HTML rendering
99
96
  * @returns {Object} An Route object already configured
100
- * @example <caption> Defining a simple GET route:</caption>
101
- * setStatic('/login', __dirname+'/public/static/views/login.html', 'text/html', 'utf8');
102
97
  */
103
98
  /**
104
99
  * Dynamic rendering example:
@@ -117,8 +112,9 @@ class SlowerRouter {
117
112
  * age: 29
118
113
  * }));
119
114
  */
120
- setDynamic = function (path, file = '', mime = '', replacementData) {
121
- let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8')
115
+ setDynamic = function (path, file = '', mime = '', replacementData = null) {
116
+ let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8');
117
+ if (file.includes('{%}')) { file = file.replace(/\{\%\}/gim, path.replace(/\//gim,'')); }
122
118
  let stat = new Route(path, 'GET', (req, res) => {
123
119
  let data, targetFile, extension, targetMime, targetEncoding;
124
120
  if (fs.existsSync(file) && fs.lstatSync(file).isDirectory()) {
@@ -143,7 +139,7 @@ class SlowerRouter {
143
139
  res.end();
144
140
  });
145
141
  this.routes.push(stat);
146
- return stat;
142
+ return this;
147
143
  }
148
144
 
149
145
  // SERVES FILES FOR SPECIFIC PATHS. WILDCARS ALLOWED. BE CAREFUL - PATH TRAVERSAL MAY BE POSSIBLE
@@ -156,13 +152,13 @@ class SlowerRouter {
156
152
  * @param {String} path The route that will be defined
157
153
  * @param {String} file The file path that will be used to respond to the route
158
154
  * @param {String} mime The file's mime type
159
- * @param {String} encoding The file's encoding (defaults to UTF-8)
160
155
  * @returns {Object} An Route object already configured
161
156
  * @example <caption> Defining a simple GET route:</caption>
162
- * setStatic('/login', __dirname+'/public/static/views/login.html', 'text/html', 'utf8');
157
+ * setStatic('/login', __dirname+'/public/static/views/{%}.html', 'text/html');
163
158
  */
164
159
  setStatic = function (path, file = '', mime = '') {
165
- let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8')
160
+ let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8');
161
+ if (file.includes('{%}')) { file = file.replace(/\{\%\}/gim, path.replace(/\//gim,'')); }
166
162
  let stat = new Route(path, 'GET', (req, res) => {
167
163
  let data, targetFile, extension, targetMime, targetEncoding;
168
164
  if (fs.existsSync(file) && fs.lstatSync(file).isDirectory()) {
@@ -184,7 +180,7 @@ class SlowerRouter {
184
180
  res.end();
185
181
  });
186
182
  this.routes.push(stat);
187
- return stat;
183
+ return this;
188
184
  }
189
185
 
190
186
  /**
@@ -192,10 +188,8 @@ class SlowerRouter {
192
188
  * @category Router
193
189
  * @param {String} callback The function to execute for unhandled routes
194
190
  * @returns {undefined}
195
- * @example <caption> Defining a simple GET route:</caption>
196
- * setStatic('/login', __dirname+'/public/static/views/login.html', 'text/html', 'utf8');
197
191
  */
198
- setFallback = function (callback) { this.fallback = callback; }
192
+ setFallback = function (callback) { this.fallback = callback; return this; }
199
193
 
200
194
  // SERVES FILES FOR SPECIFIC PATHS. WILDCARS ALLOWED. BE CAREFUL - PATH TRAVERSAL MAY BE POSSIBLE
201
195
  // Use app.setStatic('/*', __dirname+'/') for serving all local files.
@@ -229,9 +223,9 @@ class SlowerRouter {
229
223
  * age: 29
230
224
  * }));
231
225
  */
232
- setFallbackFile = function (file = '', mime = '', replacementData) {
226
+ setFallbackFile = function (file = '', mime = '', replacementData = null) {
233
227
  this.fallback = function fb (req,res) {
234
- let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8')
228
+ let encoding = (mime === SlowerRouter.mime_table['default'] ? undefined : 'utf-8');
235
229
  let data, targetFile, extension, targetMime, targetEncoding;
236
230
  if (fs.existsSync(file) && fs.lstatSync(file).isDirectory()) {
237
231
  targetFile = file.replace(/\//gim, '\\');
@@ -254,6 +248,7 @@ class SlowerRouter {
254
248
  res.write(data);
255
249
  res.end();
256
250
  }
251
+ return this;
257
252
  }
258
253
 
259
254
  // Sets the methods that the application will respond to. The rest is simply discarded with empty responses.
@@ -282,7 +277,7 @@ class SlowerRouter {
282
277
  res.writeHead(405); // sends the meme error 418 'i am a teapot'
283
278
  res.end();
284
279
  };
285
- return this.allowedMethods;
280
+ return this;
286
281
  }
287
282
 
288
283
  // Starts the server - listening at <host>:<port>
@@ -290,10 +285,8 @@ class SlowerRouter {
290
285
  * @category Router
291
286
  * @param {Number} port The port number the server will listen to.
292
287
  * @param {String} host The host's network interface address the server will listen into (use a falsy value or '0.0.0.0' for listening on all).
293
- * @param {Function} methods The methods that are allowed by the application. Methods that do not conform with standards are ignored.
294
- * @returns {Object} The AllowedMethods Array object.
295
- * @example <caption> Allowing only GET and POST:</caption>
296
- * app.setAllowedMethods(['GET', 'POST']);
288
+ * @param {Function} callback The function to execute after starting the server.
289
+ * @returns {Object<http.Server>} The server instance
297
290
  */
298
291
  start = function (port = 8080, host = undefined, callback = () => {}) {
299
292
  let routes = this.routes;
@@ -339,7 +332,8 @@ class SlowerRouter {
339
332
  });
340
333
  callback(server);
341
334
  if (!host) host = undefined; // Turn falsy values into undefined, for default behaviour
342
- return server.listen(port, host);
335
+ server.listen(port, host);
336
+ return this;
343
337
  }
344
338
  }
345
339
 
package/lib/utils.js CHANGED
@@ -44,7 +44,7 @@ const isSparseEqual = (str1 = '', str2 = '') => {
44
44
 
45
45
  /**
46
46
  * It's a template engine, to render HTML containing template spaces.
47
- * The charset for replacement is <{content}>
47
+ * The charset for replacement is {{content}}
48
48
  * @since 1.2.5
49
49
  *
50
50
  * @param {String} html The HTML code
@@ -52,7 +52,7 @@ const isSparseEqual = (str1 = '', str2 = '') => {
52
52
  * @return {String} The HTML with the templates replaces
53
53
  *
54
54
  * @example <caption> Rendering: </caption>
55
- * var template = 'Hello, my name is <{name}>. I\\'m <{age}> years old.';
55
+ * var template = 'Hello, my name is {{name}}. I\\'m {{age}} years old.';
56
56
  * console.log(TemplateEngine(template, {
57
57
  * name: "Krasimir",
58
58
  * age: 29
@@ -62,7 +62,7 @@ const renderDynamicHTML = (html, patterns) => {
62
62
  let template = html;
63
63
  for (let item in patterns) {
64
64
  template = html.replace(
65
- new RegExp('<{'+item+'}>', 'gim'),
65
+ new RegExp('{{'+item+'}}', 'gim'),
66
66
  patterns[item]
67
67
  );
68
68
  }
@@ -141,4 +141,6 @@ const setSocketSecurityHeaders = (req) => {
141
141
 
142
142
  const toBool = [() => true, () => false];
143
143
 
144
- module.exports = { noop, slugify, isSparseEqual, toBool, last, renderDynamicHTML, setSocketLocals, setSocketSecurityHeaders };
144
+ const clone = (object) => JSON.parse(JSON.stringify(object));
145
+
146
+ module.exports = { clone, noop, slugify, isSparseEqual, toBool, last, renderDynamicHTML, setSocketLocals, setSocketSecurityHeaders };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slower",
3
- "version": "1.1.12",
3
+ "version": "1.1.15",
4
4
  "description": "A package for simple HTTP server routing.",
5
5
  "main": "index.js",
6
6
  "directories": {
package/readme.md CHANGED
@@ -3,6 +3,116 @@
3
3
  Slower is a small web framework, express-like, but simpler and limited.
4
4
  It allows for generic route-declaration, fallback pages, and multiple middleware functions.
5
5
 
6
+ ### API Methods:
7
+
8
+ ```
9
+ app.enableStrictHeaders(): this
10
+
11
+ > Enables the use of the set of 'Strict Headers'.
12
+ > These headers increase security levels, and are a good practice to apply.
13
+ > However, using these headers in testing scenarios are not a need,
14
+ and may have buggy or negative effects. So, apply those to simulate scenarios only.
15
+ > Headers configured:
16
+ > Content-Security-Policy
17
+ > Cross-Origin-Opener-Policy
18
+ > Cross-Origin-Resource-Policy
19
+ > Origin-Agent-Cluster
20
+ > Referrer-Policy
21
+ > X-DNS-Prefetch-Control (disabled)
22
+ > X-Download-Options
23
+ > X-Frame-Options
24
+ > X-XSS-Protection (disabled)
25
+ > X-Powered-By (removed)
26
+ > Returns the own object instance, so that methods can be chained.
27
+ ```
28
+ ```
29
+ app.disableStrictHeaders(): this
30
+
31
+ > Disables the use of the set of 'Strict Headers'.
32
+ > See 'enableStrictHeaders()' for more information.
33
+ > Returns the own object instance, so that methods can be chained.
34
+ ```
35
+ ```
36
+ app.setRoute(string: path = '/', string: type = 'GET', function: callback): this
37
+
38
+ > Creates a new route for path defined in 'path', responding to the HTTP verb defined in 'type' argument.
39
+ > The callback is executed when the route is accessed.
40
+ > Returns the own object instance, so that methods can be chained.
41
+ ```
42
+ ```
43
+ app.setMiddleware(function: callback): this
44
+
45
+ > Sets a new middleware function: callback function will be accessed for every server access.
46
+ > Many middlewares can be defined, and will be applied in the order they are defined.
47
+ > Returns the own object instance, so that methods can be chained.
48
+ ```
49
+ ```
50
+ app.setDynamic(string: path, string: file = '', string: mime = '', object: replacementData = null): this
51
+
52
+ > Creates a new GET route for path defined in 'path'.
53
+ > This is a custom file-response route, configured for template rendering just before response.
54
+ > Providing an object as 'replacementData' in this format { valueToBeReplaced: valueToReplace },
55
+ allows for template rendering. The value to replace in the file, uses this notation: '<{content}>'.
56
+ > URL reference in filename:
57
+ > For direct references, it is possible to use the token '{%}' to replace the filename for the URL.
58
+ > Ex:
59
+ app.setStatic('/login', './templates/{%}.html', 'text/html');
60
+ This will access the 'login.html' file when the route '/login' is accessed.
61
+ > Example:
62
+ Responding a route for '/custom' with file 'custom.html':
63
+ app.setDynamic('/custom', './templates/custom.html', 'text/html', { smile: ':)' })
64
+ In file './templates/custom.html':
65
+ "<h2> This is a custom thing: <{smile}> </h2>"
66
+ Rendered in browser:
67
+ <h2> This is a custom thing: :) </h2>
68
+ > Returns the own object instance, so that methods can be chained.
69
+ ```
70
+ ```
71
+ app.setStatic(string: path, string: file = '', string: mime = ''): this
72
+
73
+ > Creates a new GET route for path defined in 'path', responding with the specified file and MIME type.
74
+ > URL reference in filename:
75
+ > For direct references, it is possible to use the token '{%}' to replace the filename for the URL.
76
+ > Ex:
77
+ app.setStatic('/login', './templates/{%}.html', 'text/html');
78
+ This will access the 'login.html' file when the route '/login' is accessed.
79
+ > Example: A route for '/login' page, responding with 'login.html' file
80
+ setStatic('/login', __dirname+'/public/static/views/login.html', 'text/html');
81
+ > Returns the own object instance, so that methods can be chained.
82
+ ```
83
+ ```
84
+ app.setFallback(function: callback): this
85
+
86
+ > Creates a function for fallback state. When no other routes intercept the route, this will be used.
87
+ > Special use for 'page not found' fallback pages or highly customized routes and situations.
88
+ > Returns the own object instance, so that methods can be chained.
89
+ ```
90
+ ```
91
+ app.setFallbackFile (string: file = '', string: mime = '', object: replacementData = null): this
92
+
93
+ > Creates a function for fallback state. When no other routes intercept the route, this will be used.
94
+ > Equivalent to setFallback, but responds with a file. Allows for template rendering.
95
+ > See 'setDynamic' for more information about template rendering.
96
+ > Special use for 'page not found' fallback pages, ex: './e404.html'.
97
+ > Returns the own object instance, so that methods can be chained.
98
+ ```
99
+ ```
100
+ app.setAllowedMethods(array: methods = []): this
101
+
102
+ > Sets a list of methods to respond to.
103
+ > By using this, it is possible to restrict the application to avoid
104
+ responding to dangerous HTTP verbs, such as 'DELETE'.
105
+ > By default, all methods are allowed (see Slower.constructor.http_methods)
106
+ > Calling this function without parameters is an easy way to block responses to all requests (lock server).
107
+ > Returns the own object instance, so that methods can be chained.
108
+ ```
109
+ ```
110
+ app.start(number|string: port = 8080, string: host = undefined, function: callback = ()=>{}): this
111
+
112
+ > Starts the server, at a specific host and port, then calling the callback function.
113
+ > Not defining a specific port or host will start the server at '0.0.0.0:8080'.
114
+ > Returns the own object instance, so that methods can be chained.
115
+ ```
6
116
 
7
117
  Example usage:
8
118
  ```
@@ -16,7 +126,7 @@ app.setMiddleware((req, res) => {
16
126
  console.log(`${req.time} - ${req.method} : ${req.url}`);
17
127
  });
18
128
 
19
- app.setStatic('/favicon.ico', __dirname+'/public/favicon.ico');
129
+ app.setStatic('/favicon.ico', __dirname+'/public/{%}');
20
130
 
21
131
  app.setRoute('/', 'GET', (req, res) => {
22
132
  res.writeHead(200, { 'Content-Type': 'text/html' });
@@ -46,6 +156,7 @@ app.start(port, null, () => {
46
156
  console.log(`Running on localhost:${port}`);
47
157
  console.log(app);
48
158
  });
159
+
49
160
  ```
50
161
  ### API modifications on 'net.Socket' instances:
51
162
  - The API modifies every ```net.Socket``` instance BEFORE it is passed
@@ -71,6 +182,7 @@ So, considering the common callback of ```(req, res)```, the session container w
71
182
  methods do exacly that. The strict headers are disabled by default, as some resources are too strict,
72
183
  but it is also possible to enable them all, and then set a middleware to override any header.
73
184
  - Headers set by 'enableStrictHeaders':
185
+ ```
74
186
  Content-Security-Policy: default-src=none; script-src=self; connect-src=self; img-src=self;
75
187
  style-src=self; frame-ancestors=none; form-action=self;
76
188
  Cross-Origin-Opener-Policy: same-origin
@@ -84,3 +196,4 @@ So, considering the common callback of ```(req, res)```, the session container w
84
196
  X-Frame-Options: DENY
85
197
  X-Powered-By: (This header is removed if a response includes it)
86
198
  X-XSS-Protection: 0
199
+ ```