pixl-server-web 2.0.13 → 2.0.14

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 CHANGED
@@ -21,6 +21,7 @@ This module is a component for use in [pixl-server](https://www.github.com/jhuck
21
21
  * [http_regex_json](#http_regex_json)
22
22
  * [http_response_headers](#http_response_headers)
23
23
  * [http_code_response_headers](#http_code_response_headers)
24
+ * [http_uri_response_headers](#http_uri_response_headers)
24
25
  * [http_timeout](#http_timeout)
25
26
  * [http_request_timeout](#http_request_timeout)
26
27
  * [http_keep_alives](#http_keep_alives)
@@ -251,7 +252,7 @@ This is a regular expression string used to determine if the incoming POST reque
251
252
 
252
253
  ## http_response_headers
253
254
 
254
- This param allows you to send back any additional custom HTTP headers with each response. Set the param to an object containing keys for each header, like this:
255
+ This param allows you to send back additional custom HTTP headers with *every* response. Set the param to an object containing keys for each header, like this:
255
256
 
256
257
  ```json
257
258
  {
@@ -290,6 +291,36 @@ An actual useful case would be to include a [Retry-After](https://developer.mozi
290
291
 
291
292
  This would give a hint to clients when they receive a `429` (Too Many Requests) response from the web server, that they should wait `10` seconds before trying again.
292
293
 
294
+ ## http_uri_response_headers
295
+
296
+ This property allows you to include *conditional* response headers, based on regular expression matches on incoming request URIs. You may specify multiple patterns, and multiple headers to inject for each URI match. For example, you can instruct the web server to send back custom headers for a specific URI prefix, like this:
297
+
298
+ ```json
299
+ {
300
+ "http_uri_response_headers": {
301
+ "^/secret": {
302
+ "X-Message": "You found the secret area!",
303
+ "X-Foo": "Bar"
304
+ }
305
+ }
306
+ }
307
+ ```
308
+
309
+ An actual useful case would be to include a set of [CSP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) for all HTML files, and URIs that end in a slash (which typically present an HTML file). Example:
310
+
311
+ ```json
312
+ {
313
+ "http_uri_response_headers": {
314
+ "(\/|\\.html)$": {
315
+ "Content-Security-Policy": "default-src 'none'; script-src 'self'; script-src-elem 'self'; script-src-attr 'unsafe-inline'; style-src 'self' 'unsafe-inline'; style-src-attr 'unsafe-inline'; manifest-src 'self';img-src 'self' data: blob:; font-src 'self'; connect-src 'self' ws: wss:; media-src 'self' blob:; worker-src 'self' blob:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';",
316
+ "X-Content-Type-Options": "nosniff",
317
+ "Referrer-Policy": "strict-origin-when-cross-origin",
318
+ "Permissions-Policy": "camera=(), microphone=(), geolocation=(), fullscreen=()"
319
+ }
320
+ }
321
+ }
322
+ ```
323
+
293
324
  ## http_timeout
294
325
 
295
326
  This sets the idle socket timeout for all incoming HTTP requests, in seconds. If omitted, the Node.js default is 120 seconds. Example:
package/lib/response.js CHANGED
@@ -82,11 +82,25 @@ module.exports = class Response {
82
82
  // merge in conditional headers based on response code
83
83
  var code_headers = this.config.get('http_code_response_headers');
84
84
  if (code_headers && (http_code in code_headers)) {
85
+ this.logDebug(9, "Injecting custom response headers for HTTP code: " + http_code, code_headers[http_code]);
85
86
  for (var key in code_headers[http_code]) {
86
87
  headers[key] = code_headers[http_code][key];
87
88
  }
88
89
  }
89
90
 
91
+ // merge in conditional headers based on URI
92
+ var uri = request.url;
93
+ if (!this.config.get('http_full_uri_match')) uri = uri.replace(/\?.*$/, '');
94
+
95
+ this.uriResponseHeaders.forEach( function(item) {
96
+ if (!uri.match(item.regexp)) return;
97
+ self.logDebug(9, "Injecting custom response headers for URI match: " + item.regexp, item.headers);
98
+
99
+ for (var key in item.headers) {
100
+ headers[key] = item.headers[key];
101
+ }
102
+ } );
103
+
90
104
  // use duck typing to see if we have a stream, buffer or string
91
105
  var is_stream = (body && body.pipe);
92
106
  var is_buffer = (body && body.fill);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pixl-server-web",
3
- "version": "2.0.13",
3
+ "version": "2.0.14",
4
4
  "description": "A web server component for the pixl-server framework.",
5
5
  "author": "Joseph Huckaby <jhuckaby@gmail.com>",
6
6
  "homepage": "https://github.com/jhuckaby/pixl-server-web",
package/web_server.js CHANGED
@@ -267,6 +267,19 @@ class WebServer extends Component {
267
267
  this.logDebug(5, "Setting bind address to localhost for debug mode");
268
268
  this.config.set('http_bind_address', 'localhost');
269
269
  }
270
+
271
+ // pre-compile regexps for http_uri_response_headers
272
+ this.uriResponseHeaders = [];
273
+ var patterns = this.config.get('http_uri_response_headers');
274
+ if (patterns) {
275
+ for (var pat in patterns) {
276
+ this.logDebug(5, "Adding custom response headers for URI pattern: " + pat, patterns[pat]);
277
+ this.uriResponseHeaders.push({
278
+ regexp: new RegExp(pat),
279
+ headers: patterns[pat]
280
+ });
281
+ }
282
+ }
270
283
  }
271
284
 
272
285
  postStartupMessage() {