pixl-server-web 1.3.25 → 1.3.26
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 +223 -97
- package/lib/response.js +57 -4
- package/package.json +1 -1
- package/web_server.js +2 -0
package/README.md
CHANGED
|
@@ -111,26 +111,26 @@ This module is a component for use in [pixl-server](https://www.github.com/jhuck
|
|
|
111
111
|
|
|
112
112
|
Use [npm](https://www.npmjs.com/) to install the module:
|
|
113
113
|
|
|
114
|
-
```
|
|
114
|
+
```sh
|
|
115
115
|
npm install pixl-server pixl-server-web
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
Here is a simple usage example. Note that the component's official name is `WebServer`, so that is what you should use for the configuration key, and for gaining access to the component via your server object.
|
|
119
119
|
|
|
120
120
|
```js
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
const PixlServer = require('pixl-server');
|
|
122
|
+
let server = new PixlServer({
|
|
123
123
|
|
|
124
124
|
__name: 'MyServer',
|
|
125
125
|
__version: "1.0",
|
|
126
126
|
|
|
127
127
|
config: {
|
|
128
|
-
"log_dir": "/
|
|
128
|
+
"log_dir": "/let/log",
|
|
129
129
|
"debug_level": 9,
|
|
130
130
|
|
|
131
131
|
"WebServer": {
|
|
132
132
|
"http_port": 80,
|
|
133
|
-
"http_htdocs_dir": "/
|
|
133
|
+
"http_htdocs_dir": "/let/www/html"
|
|
134
134
|
}
|
|
135
135
|
},
|
|
136
136
|
|
|
@@ -162,7 +162,7 @@ components: [
|
|
|
162
162
|
]
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
This example is a very simple web server configuration, which will listen on port 80 and serve static files out of `/
|
|
165
|
+
This example is a very simple web server configuration, which will listen on port 80 and serve static files out of `/let/www/html`. However, if the URI is `/my/custom/uri`, a custom callback function is fired and can serve up any response it wants. This is a great way to implement an API.
|
|
166
166
|
|
|
167
167
|
# Configuration
|
|
168
168
|
|
|
@@ -176,7 +176,7 @@ This is the main port to listen on. The standard web port is 80, but note that
|
|
|
176
176
|
|
|
177
177
|
If you would like to have the server listen on additional ports, add them here as an array. Example:
|
|
178
178
|
|
|
179
|
-
```
|
|
179
|
+
```json
|
|
180
180
|
{
|
|
181
181
|
"http_port": 80,
|
|
182
182
|
"http_alt_ports": [ 3000, 8080 ]
|
|
@@ -187,7 +187,7 @@ If you would like to have the server listen on additional ports, add them here a
|
|
|
187
187
|
|
|
188
188
|
Optionally specify an exact local IP address to bind the listeners to. By default this binds to all available addresses on the machine. Example:
|
|
189
189
|
|
|
190
|
-
```
|
|
190
|
+
```json
|
|
191
191
|
{
|
|
192
192
|
"http_bind_address": "127.0.0.1"
|
|
193
193
|
}
|
|
@@ -197,7 +197,7 @@ This example would cause the server to *only* listen on localhost, and not any e
|
|
|
197
197
|
|
|
198
198
|
## http_htdocs_dir
|
|
199
199
|
|
|
200
|
-
This is the path to the directory to serve static files out of, e.g. `/
|
|
200
|
+
This is the path to the directory to serve static files out of, e.g. `/let/www/html`.
|
|
201
201
|
|
|
202
202
|
## http_max_upload_size
|
|
203
203
|
|
|
@@ -239,7 +239,7 @@ This is a regular expression string used to determine if the incoming POST reque
|
|
|
239
239
|
|
|
240
240
|
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:
|
|
241
241
|
|
|
242
|
-
```
|
|
242
|
+
```json
|
|
243
243
|
{
|
|
244
244
|
"http_response_headers": {
|
|
245
245
|
"X-My-Custom-Header": "12345",
|
|
@@ -252,7 +252,7 @@ This param allows you to send back any additional custom HTTP headers with each
|
|
|
252
252
|
|
|
253
253
|
This property allows you to include *conditional* response headers, based on the HTTP response code. For example, you can instruct the web server to send back a custom header with `404` (File Not Found) responses, like this:
|
|
254
254
|
|
|
255
|
-
```
|
|
255
|
+
```json
|
|
256
256
|
{
|
|
257
257
|
"http_code_response_headers": {
|
|
258
258
|
"404": {
|
|
@@ -264,7 +264,7 @@ This property allows you to include *conditional* response headers, based on the
|
|
|
264
264
|
|
|
265
265
|
An actual useful case would be to include a [Retry-After](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header with all `429` (Too Many Requests) responses, like this:
|
|
266
266
|
|
|
267
|
-
```
|
|
267
|
+
```json
|
|
268
268
|
{
|
|
269
269
|
"http_code_response_headers": {
|
|
270
270
|
"429": {
|
|
@@ -280,7 +280,7 @@ This would give a hint to clients when they receive a `429` (Too Many Requests)
|
|
|
280
280
|
|
|
281
281
|
This sets the idle socket timeout for all incoming HTTP requests, in seconds. If omitted, the Node.js default is 120 seconds. Example:
|
|
282
282
|
|
|
283
|
-
```
|
|
283
|
+
```json
|
|
284
284
|
{
|
|
285
285
|
"http_timeout": 120
|
|
286
286
|
}
|
|
@@ -292,7 +292,7 @@ This only applies to reading from sockets when data is expected. It is an *idle
|
|
|
292
292
|
|
|
293
293
|
This property sets an actual hard request timeout for all incoming requests. If the total combined request processing, handling and response time exceeds this value, specified in seconds, then the request is aborted and a `HTTP 408 Request Timeout` response is sent back to the client. This defaults to `0` (disabled). Example use:
|
|
294
294
|
|
|
295
|
-
```
|
|
295
|
+
```json
|
|
296
296
|
{
|
|
297
297
|
"http_request_timeout": 300
|
|
298
298
|
}
|
|
@@ -306,7 +306,7 @@ This controls the [HTTP Keep-Alive](https://en.wikipedia.org/wiki/HTTP_persisten
|
|
|
306
306
|
|
|
307
307
|
### default
|
|
308
308
|
|
|
309
|
-
```
|
|
309
|
+
```json
|
|
310
310
|
{
|
|
311
311
|
"http_keep_alives": "default"
|
|
312
312
|
}
|
|
@@ -316,7 +316,7 @@ This **enables** Keep-Alives for all incoming connections by default, unless the
|
|
|
316
316
|
|
|
317
317
|
### request
|
|
318
318
|
|
|
319
|
-
```
|
|
319
|
+
```json
|
|
320
320
|
{
|
|
321
321
|
"http_keep_alives": "request"
|
|
322
322
|
}
|
|
@@ -326,7 +326,7 @@ This **disables** Keep-Alives for all incoming connections by default, unless th
|
|
|
326
326
|
|
|
327
327
|
### close
|
|
328
328
|
|
|
329
|
-
```
|
|
329
|
+
```json
|
|
330
330
|
{
|
|
331
331
|
"http_keep_alives": "close"
|
|
332
332
|
}
|
|
@@ -336,9 +336,9 @@ This completely disables Keep-Alives for all connections. All requests result i
|
|
|
336
336
|
|
|
337
337
|
## http_keep_alive_timeout
|
|
338
338
|
|
|
339
|
-
This sets the HTTP Keep-Alive idle timeout for all sockets, measured in seconds. If omitted, the Node.js default is 5 seconds. See [server.keepAliveTimeout](https://nodejs.org/api/http.html#
|
|
339
|
+
This sets the HTTP Keep-Alive idle timeout for all sockets, measured in seconds. If omitted, the Node.js default is 5 seconds. See [server.keepAliveTimeout](https://nodejs.org/api/http.html#serverkeepalivetimeout) for details. Example:
|
|
340
340
|
|
|
341
|
-
```
|
|
341
|
+
```json
|
|
342
342
|
{
|
|
343
343
|
"http_keep_alive_timeout": 5
|
|
344
344
|
}
|
|
@@ -348,7 +348,7 @@ This sets the HTTP Keep-Alive idle timeout for all sockets, measured in seconds.
|
|
|
348
348
|
|
|
349
349
|
This sets a special preliminary timeout for brand new sockets when they are first connected, measured in seconds. If an HTTP request doesn't come over the socket within this timeout (specified in seconds), then the socket is hard closed. This timeout should always be set lower than the [http_timeout](#http_timeout) if used. This defaults to `0` (disabled). Example use:
|
|
350
350
|
|
|
351
|
-
```
|
|
351
|
+
```json
|
|
352
352
|
{
|
|
353
353
|
"http_socket_prelim_timeout": 3
|
|
354
354
|
}
|
|
@@ -362,7 +362,7 @@ The idea here is to prevent certain DDoS-style attacks, where an attacker opens
|
|
|
362
362
|
|
|
363
363
|
This allows you to set a maximum number of requests to allow per Keep-Alive connection. It defaults to `0` which means unlimited. If set, and the maximum is reached, a `Connection: close` header is returned, politely asking the client to close the connection. It does not actually hard-close the socket. Example:
|
|
364
364
|
|
|
365
|
-
```
|
|
365
|
+
```json
|
|
366
366
|
{
|
|
367
367
|
"http_max_requests_per_connection": 100
|
|
368
368
|
}
|
|
@@ -372,16 +372,16 @@ This allows you to set a maximum number of requests to allow per Keep-Alive conn
|
|
|
372
372
|
|
|
373
373
|
This allows you to set various options for the automatic GZip compression in HTTP responses. Example:
|
|
374
374
|
|
|
375
|
-
```
|
|
375
|
+
```json
|
|
376
376
|
{
|
|
377
|
-
http_gzip_opts: {
|
|
378
|
-
level: 6,
|
|
379
|
-
memLevel: 8
|
|
377
|
+
"http_gzip_opts": {
|
|
378
|
+
"level": 6,
|
|
379
|
+
"memLevel": 8
|
|
380
380
|
}
|
|
381
381
|
}
|
|
382
382
|
```
|
|
383
383
|
|
|
384
|
-
Please see the Node [Zlib Class Options](https://nodejs.org/api/zlib.html#
|
|
384
|
+
Please see the Node [Zlib Class Options](https://nodejs.org/api/zlib.html#class-options) for more details on what can be set here.
|
|
385
385
|
|
|
386
386
|
## http_enable_brotli
|
|
387
387
|
|
|
@@ -393,26 +393,26 @@ Brotli is a newer compression format written by Google, which was added to Node.
|
|
|
393
393
|
|
|
394
394
|
If [http_enable_brotli](#http_enable_brotli) is set to `true`, then you can set various options via the `http_brotli_opts` configuration property. Example:
|
|
395
395
|
|
|
396
|
-
```
|
|
396
|
+
```json
|
|
397
397
|
{
|
|
398
|
-
http_brotli_opts: {
|
|
399
|
-
chunkSize: 16 * 1024,
|
|
400
|
-
mode: "text",
|
|
401
|
-
level: 4,
|
|
402
|
-
hint: 0
|
|
398
|
+
"http_brotli_opts": {
|
|
399
|
+
"chunkSize": 16 * 1024,
|
|
400
|
+
"mode": "text",
|
|
401
|
+
"level": 4,
|
|
402
|
+
"hint": 0
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
```
|
|
406
406
|
|
|
407
|
-
See the Node [Brotli Class Options](https://nodejs.org/api/zlib.html#
|
|
407
|
+
See the Node [Brotli Class Options](https://nodejs.org/api/zlib.html#class-brotlioptions) for more details on what can be set here. Note that `mode` is a convenience shortcut for `zlib.constants.BROTLI_PARAM_MODE` (which can set to `text`, `font` or `generic`), `level` is a shortcut for `zlib.constants.BROTLI_PARAM_QUALITY`, and `hint` is a shortcut for `zlib.constants.BROTLI_PARAM_SIZE_HINT`.
|
|
408
408
|
|
|
409
409
|
## http_default_acl
|
|
410
410
|
|
|
411
411
|
This allows you to configure the default [ACL](https://en.wikipedia.org/wiki/Access_control_list), which is only used for URI handlers that register themselves as private. To customize it, specify an array of [IPv4](https://en.wikipedia.org/wiki/IPv4) and/or [IPv6](https://en.wikipedia.org/wiki/IPv6) addresses, partials or [CIDR blocks](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). It defaults to [localhost](https://en.wikipedia.org/wiki/Localhost) plus the [IPv4 private reserved](https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses) and [IPv6 private reserved ranges](https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses). Example:
|
|
412
412
|
|
|
413
|
-
```
|
|
413
|
+
```json
|
|
414
414
|
{
|
|
415
|
-
http_default_acl: [
|
|
415
|
+
"http_default_acl": ["127.0.0.1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "::1/128", "fd00::/8", "169.254.0.0/16", "fe80::/10"]
|
|
416
416
|
}
|
|
417
417
|
```
|
|
418
418
|
|
|
@@ -422,6 +422,10 @@ See [Access Control Lists](#access-control-lists) below for more details.
|
|
|
422
422
|
|
|
423
423
|
This boolean allows you to enable transaction logging in the web server. It defaults to `false` (disabled). See [Transaction Logging](#transaction-logging) below for details.
|
|
424
424
|
|
|
425
|
+
## http_log_request_details
|
|
426
|
+
|
|
427
|
+
This boolean adds verbose detail in the transaction log. It defaults to `false` (disabled). See [Transaction Logging](#transaction-logging) below for details.
|
|
428
|
+
|
|
425
429
|
## http_regex_log
|
|
426
430
|
|
|
427
431
|
If [http_log_requests](#http_log_requests) is enabled, this allows you to specify a regular expression to match against incoming request URIs. Only requests that match will be logged. It defaults to match all URIs (`.+`). See [Transaction Logging](#transaction-logging) below for details.
|
|
@@ -452,7 +456,7 @@ This integer specifies the maximum number of concurrent requests to allow. It d
|
|
|
452
456
|
|
|
453
457
|
The idea here is that you can set [http_max_connections](#http_max_connections) to a much higher value, for things like load balancers pre-opening connections or clients using a pool of keep-alive connections, but then only allow your application code to process a smaller amount of requests in parallel. For example:
|
|
454
458
|
|
|
455
|
-
```
|
|
459
|
+
```json
|
|
456
460
|
{
|
|
457
461
|
"http_max_connections": 2048,
|
|
458
462
|
"http_max_concurrent_requests": 64
|
|
@@ -494,7 +498,7 @@ With both `http_max_queue_length` and `http_max_queue_active` set to non-zero va
|
|
|
494
498
|
|
|
495
499
|
The `http_queue_skip_uri_match` property is designed to work in conjunction with [http_max_concurrent_requests](#http_max_concurrent_requests). It allows you to specify a URI pattern match that will always skip over the queue and be processed immediately, regardless of limits. Using this feature you can allow things like health checks (possibly from a load balancer) to always be serviced, even during an overload situation. Example use:
|
|
496
500
|
|
|
497
|
-
```
|
|
501
|
+
```json
|
|
498
502
|
{
|
|
499
503
|
"http_queue_skip_uri_match": "^/server-status"
|
|
500
504
|
}
|
|
@@ -510,7 +514,7 @@ This boolean enables HTTP response header cleansing. When set to `true` it will
|
|
|
510
514
|
|
|
511
515
|
This boolean enables logging socket related errors, specifically sockets being closed unexpectedly (i.e. client closed socket, or some network error caused socket to abort). This defaults to `true`, meaning these will be logged as errors. If this generates too much log noise for your production stack, you can set the configuration property to `false`, which will only log a level 9 debug event. Example:
|
|
512
516
|
|
|
513
|
-
```
|
|
517
|
+
```json
|
|
514
518
|
{
|
|
515
519
|
"http_log_socket_errors": false
|
|
516
520
|
}
|
|
@@ -526,7 +530,7 @@ Example error log entry:
|
|
|
526
530
|
|
|
527
531
|
When this boolean is set to `true`, [Custom URI Handlers](#custom-uri-handlers) will match against the *full* incoming URI, including the query string. By default this is disabled, meaning URIs are only matched using their path. Example:
|
|
528
532
|
|
|
529
|
-
```
|
|
533
|
+
```json
|
|
530
534
|
{
|
|
531
535
|
"http_full_uri_match": true
|
|
532
536
|
}
|
|
@@ -536,7 +540,7 @@ When this boolean is set to `true`, [Custom URI Handlers](#custom-uri-handlers)
|
|
|
536
540
|
|
|
537
541
|
By default, we use the Node.js core [Query String](https://nodejs.org/api/querystring.html) module to parse query strings. This module handles duplicate query params by converting them to arrays. For example, an incoming URI such as `/something?foo=bar1&foo=bar2&name=joe` would produce the following `args.query` object:
|
|
538
542
|
|
|
539
|
-
```
|
|
543
|
+
```json
|
|
540
544
|
{
|
|
541
545
|
"foo": ["bar1", "bar2"],
|
|
542
546
|
"name": "joe"
|
|
@@ -545,7 +549,7 @@ By default, we use the Node.js core [Query String](https://nodejs.org/api/querys
|
|
|
545
549
|
|
|
546
550
|
However, if you set `http_flatten_query` to `true` in your configuration, the web server will "flatten" query string parameters, so that duplicate keys will be combined into one, with the latter prevailing. Example:
|
|
547
551
|
|
|
548
|
-
```
|
|
552
|
+
```json
|
|
549
553
|
{
|
|
550
554
|
"foo": "bar2",
|
|
551
555
|
"name": "joe"
|
|
@@ -589,7 +593,7 @@ If HTTPS mode is enabled, this is the port to listen on for secure requests. Th
|
|
|
589
593
|
|
|
590
594
|
If you would like to have the server listen on additional HTTPS ports, add them here as an array. Example:
|
|
591
595
|
|
|
592
|
-
```
|
|
596
|
+
```json
|
|
593
597
|
{
|
|
594
598
|
"https_port": 443,
|
|
595
599
|
"https_alt_ports": [ 9000, 9001 ]
|
|
@@ -622,9 +626,9 @@ X-Forwarded-Proto: https
|
|
|
622
626
|
|
|
623
627
|
The `https_header_detect` property allows you to define any number of header regular expression matches, that will "pseudo-enable" SSL mode in the web server. Meaning, the `args.request.headers.ssl` property will be set to `true`, and calls to `server.getSelfURL()` will have a `https://` prefix. Here is an example configuration, which detects many commonly used headers:
|
|
624
628
|
|
|
625
|
-
```
|
|
629
|
+
```json
|
|
626
630
|
{
|
|
627
|
-
https_header_detect: {
|
|
631
|
+
"https_header_detect": {
|
|
628
632
|
"Front-End-Https": "^on$",
|
|
629
633
|
"X-Url-Scheme": "^https$",
|
|
630
634
|
"X-Forwarded-Protocol": "^https$",
|
|
@@ -710,15 +714,15 @@ Note that the `Content-Type` response header is automatically set based on the t
|
|
|
710
714
|
If you would like to host static files in other places besides [http_htdocs_dir](#http_htdocs_dir), possibly with different options, then look no further than the `addDirectoryHandler()` method. This allows you to set up static file handling with a custom base URI, a custom base directory on disk, and apply other options as well. You can call this method as many times as you like to setup multiple static file directories. Example:
|
|
711
715
|
|
|
712
716
|
```js
|
|
713
|
-
server.WebServer.addDirectoryHandler( /^\/mycustomdir/, '/
|
|
717
|
+
server.WebServer.addDirectoryHandler( /^\/mycustomdir/, '/let/www/custom' );
|
|
714
718
|
```
|
|
715
719
|
|
|
716
|
-
The above example would catch all incoming requests starting with `/mycustomdir`, and serve up static files inside of the `/
|
|
720
|
+
The above example would catch all incoming requests starting with `/mycustomdir`, and serve up static files inside of the `/let/www/custom` directory on disk (and possibly nested directories as well). So a URL such as `http://MYSERVER/mycustomdir/foo/file1.txt` would map to the file `/let/www/custom/foo/file1.txt` on disk.
|
|
717
721
|
|
|
718
722
|
In this case a default TTL is applied to all files via [http_static_ttl](#http_static_ttl). If you would like to customize the TTL for your custom static directory, as well as specify other options, pass in an object as the 3rd argument to `addDirectoryHandler()`. Example of this:
|
|
719
723
|
|
|
720
724
|
```js
|
|
721
|
-
server.WebServer.addDirectoryHandler( /^\/mycustomdir/, '/
|
|
725
|
+
server.WebServer.addDirectoryHandler( /^\/mycustomdir/, '/let/www/custom', {
|
|
722
726
|
acl: true
|
|
723
727
|
ttl: 3600,
|
|
724
728
|
headers: {
|
|
@@ -751,7 +755,7 @@ callback(
|
|
|
751
755
|
);
|
|
752
756
|
```
|
|
753
757
|
|
|
754
|
-
The content body can be a string, a [Buffer](https://nodejs.org/api/buffer.html) object, or a [readable stream](https://nodejs.org/api/stream.html#
|
|
758
|
+
The content body can be a string, a [Buffer](https://nodejs.org/api/buffer.html) object, or a [readable stream](https://nodejs.org/api/stream.html#class-streamreadable).
|
|
755
759
|
|
|
756
760
|
### Custom Response
|
|
757
761
|
|
|
@@ -760,7 +764,7 @@ The second type of response is to send content directly to the underlying Node.j
|
|
|
760
764
|
```js
|
|
761
765
|
server.WebServer.addURIHandler( '/my/custom/uri', 'Custom Name', function(args, callback) {
|
|
762
766
|
// send custom raw response
|
|
763
|
-
|
|
767
|
+
let response = args.response;
|
|
764
768
|
response.writeHead( 200, "OK", { 'Content-Type': "text/html" } );
|
|
765
769
|
response.write( "Hello this is custom content!\n" );
|
|
766
770
|
response.end();
|
|
@@ -854,7 +858,7 @@ Your URI handler function is passed an `args` object containing the following pr
|
|
|
854
858
|
|
|
855
859
|
### args.request
|
|
856
860
|
|
|
857
|
-
This is a reference to the underlying [Node.js server request](https://nodejs.org/api/http.html#
|
|
861
|
+
This is a reference to the underlying [Node.js server request](https://nodejs.org/api/http.html#class-httpincomingmessage) object. From this you have access to things like:
|
|
858
862
|
|
|
859
863
|
| Property | Description |
|
|
860
864
|
|----------|-------------|
|
|
@@ -864,11 +868,11 @@ This is a reference to the underlying [Node.js server request](https://nodejs.or
|
|
|
864
868
|
| `request.url` | The complete URI of the request (sans protocol and hostname). |
|
|
865
869
|
| `request.socket` | A reference to the underlying socket connection for the request. |
|
|
866
870
|
|
|
867
|
-
For more detailed documentation on the request object, see Node's [http.IncomingMessage](https://nodejs.org/api/http.html#
|
|
871
|
+
For more detailed documentation on the request object, see Node's [http.IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage).
|
|
868
872
|
|
|
869
873
|
### args.response
|
|
870
874
|
|
|
871
|
-
This is a reference to the underlying [Node.js server response](https://nodejs.org/api/http.html#
|
|
875
|
+
This is a reference to the underlying [Node.js server response](https://nodejs.org/api/http.html#class-httpserverresponse) object. From this you have access to things like:
|
|
872
876
|
|
|
873
877
|
| Property / Method() | Description |
|
|
874
878
|
|----------|-------------|
|
|
@@ -880,14 +884,16 @@ This is a reference to the underlying [Node.js server response](https://nodejs.o
|
|
|
880
884
|
| `response.write()` | This writes a chunk of data to the socket. |
|
|
881
885
|
| `response.end()` | This indicates that the response has been completely sent. |
|
|
882
886
|
|
|
883
|
-
For more detailed documentation on the response object, see Node's [http.ServerResponse](https://nodejs.org/api/http.html#
|
|
887
|
+
For more detailed documentation on the response object, see Node's [http.ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse).
|
|
884
888
|
|
|
885
889
|
### args.ip
|
|
886
890
|
|
|
887
|
-
This will be set to the user's remote IP address.
|
|
891
|
+
This will be set to the user's remote IP address. Generally, it will be set to the *first public IP address* if multiple addresses are provided via proxy HTTP headers and the socket.
|
|
888
892
|
|
|
889
893
|
Meaning, if the user is sitting behind one or more proxy servers, *or* your web server is behind a load balancer, this will attempt to locate the user's true public (non-private) IP address. If none is found, it'll just return the first IP address, honoring proxy headers before the socket (which is usually correct).
|
|
890
894
|
|
|
895
|
+
See [http_public_ip_offset](https://github.com/jhuckaby/pixl-server-web#http_public_ip_offset) for details on customizing the behavior of this property.
|
|
896
|
+
|
|
891
897
|
If you just want the socket IP by itself, you can get it from `args.request.socket.remoteAddress`.
|
|
892
898
|
|
|
893
899
|
### args.ips
|
|
@@ -914,14 +920,14 @@ This will be an object containing key/value pairs from the URL query string, if
|
|
|
914
920
|
|
|
915
921
|
Duplicate query params become an array. For example, an incoming URI such as `/something?foo=bar1&foo=bar2&name=joe` would produce the following `args.query` object:
|
|
916
922
|
|
|
917
|
-
```
|
|
923
|
+
```json
|
|
918
924
|
{
|
|
919
925
|
"foo": ["bar1", "bar2"],
|
|
920
926
|
"name": "joe"
|
|
921
927
|
}
|
|
922
928
|
```
|
|
923
929
|
|
|
924
|
-
See [http_flatten_query](#http_flatten_query) if you would rather
|
|
930
|
+
See [http_flatten_query](#http_flatten_query) if you would rather duplicate query parameters be flattened (latter prevails).
|
|
925
931
|
|
|
926
932
|
### args.params
|
|
927
933
|
|
|
@@ -960,7 +966,7 @@ All temp files are automatically deleted at the end of the request.
|
|
|
960
966
|
This is an object parsed from the incoming `Cookie` HTTP header, if present. The contents will be key/value pairs for each semicolon-separated cookie provided. For example, if the client sent in a `session_id` cookie, it could be accessed like this:
|
|
961
967
|
|
|
962
968
|
```js
|
|
963
|
-
|
|
969
|
+
let session_id = args.cookies['session_id'];
|
|
964
970
|
```
|
|
965
971
|
|
|
966
972
|
### args.perf
|
|
@@ -1043,13 +1049,16 @@ The log columns are configurable in pixl-server, but are typically the following
|
|
|
1043
1049
|
|
|
1044
1050
|
The `data` column is a JSON document containing various bits of additional information about the request. Here is a formatted example:
|
|
1045
1051
|
|
|
1046
|
-
```
|
|
1052
|
+
```json
|
|
1047
1053
|
{
|
|
1048
1054
|
"id": "r4",
|
|
1049
1055
|
"proto": "http",
|
|
1056
|
+
"ip": "::ffff:127.0.0.1",
|
|
1050
1057
|
"ips": [
|
|
1051
1058
|
"::ffff:127.0.0.1"
|
|
1052
1059
|
],
|
|
1060
|
+
"port": 3012,
|
|
1061
|
+
"socket": "c13",
|
|
1053
1062
|
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17",
|
|
1054
1063
|
"host": "localhost",
|
|
1055
1064
|
"perf": {
|
|
@@ -1071,30 +1080,145 @@ The `data` column is a JSON document containing various bits of additional infor
|
|
|
1071
1080
|
|
|
1072
1081
|
Here are descriptions of the data JSON properties:
|
|
1073
1082
|
|
|
1074
|
-
| Property | Description |
|
|
1075
|
-
|
|
1076
|
-
| `id` | The internal ID for the request. |
|
|
1077
|
-
| `proto` | The protocol of the request (`http` or `https`). |
|
|
1078
|
-
| `
|
|
1079
|
-
| `
|
|
1080
|
-
| `
|
|
1081
|
-
| `
|
|
1083
|
+
| Property | Type | Description |
|
|
1084
|
+
|----------|------|-------------|
|
|
1085
|
+
| `id` | String | The internal ID for the request. |
|
|
1086
|
+
| `proto` | String | The protocol of the request (`http` or `https`). |
|
|
1087
|
+
| `ip` | String | The first non-internal IP address (see [args.ip](#argsip)). |
|
|
1088
|
+
| `ips` | Array | All the client IPs as an array (includes those from proxy headers). |
|
|
1089
|
+
| `port` | Number | Which port number the request came in on. |
|
|
1090
|
+
| `socket` | String | The unique ID of the socket which served the request. |
|
|
1091
|
+
| `ua` | String | The `User-Agent` string from the request headers. |
|
|
1092
|
+
| `host` | String | The hostname from the request URL. |
|
|
1093
|
+
| `perf` | Object | Performance metrics, see below. |
|
|
1082
1094
|
|
|
1083
1095
|
The `perf` object contains performance metrics for the request, as returned from the [pixl-perf](https://www.github.com/jhuckaby/pixl-perf) module. It includes a `scale` property denoting that all the metrics are displayed in milliseconds (i.e. `1000`). The metrics themselves are in the `perf` object, and counters such as the number of bytes in/out are in the `counters` object.
|
|
1084
1096
|
|
|
1085
1097
|
If you only want to log *some* requests, but not all of them, you can specify a regular expression in the [http_regex_log](#http_regex_log) configuration property, which is matched against the incoming request URIs. Example:
|
|
1086
1098
|
|
|
1087
|
-
```
|
|
1099
|
+
```json
|
|
1088
1100
|
{
|
|
1089
1101
|
"http_regex_log": "^/my/special/path"
|
|
1090
1102
|
}
|
|
1091
1103
|
```
|
|
1092
1104
|
|
|
1105
|
+
## Request Detail Logging
|
|
1106
|
+
|
|
1107
|
+
If you set both the [http_log_requests](#http_log_requests) and [http_log_request_details](#http_log_request_details) configuration properties to `true`, pixl-server will include verbose details in the transaction logs, specifically in the JSON-formatted `data` column. It will include the raw request and raw response (if in text format), and extra details about both the request and the response. Example of the `data` column from the log, pretty-printed:
|
|
1108
|
+
|
|
1109
|
+
```json
|
|
1110
|
+
{
|
|
1111
|
+
"id": "r10",
|
|
1112
|
+
"proto": "http",
|
|
1113
|
+
"ip": "::1",
|
|
1114
|
+
"ips": [
|
|
1115
|
+
"::1"
|
|
1116
|
+
],
|
|
1117
|
+
"port": 3012,
|
|
1118
|
+
"socket": "c8",
|
|
1119
|
+
"perf": {
|
|
1120
|
+
"scale": 1000,
|
|
1121
|
+
"perf": {
|
|
1122
|
+
"total": 22.689,
|
|
1123
|
+
"queue": 0.261,
|
|
1124
|
+
"read": 15.176,
|
|
1125
|
+
"process": 1.791,
|
|
1126
|
+
"encode": 1.281,
|
|
1127
|
+
"write": 1.159
|
|
1128
|
+
},
|
|
1129
|
+
"counters": {
|
|
1130
|
+
"bytes_in": 975133,
|
|
1131
|
+
"bytes_out": 413,
|
|
1132
|
+
"num_requests": 1
|
|
1133
|
+
}
|
|
1134
|
+
},
|
|
1135
|
+
"files": {
|
|
1136
|
+
"file1": {
|
|
1137
|
+
"path": "/var/folders/11/r_0sz6s13cx1jn68l4m90zfr0000gn/T/f92cd259263698f0e19581400.LBM",
|
|
1138
|
+
"type": "application/octet-stream",
|
|
1139
|
+
"name": "V04.LBM",
|
|
1140
|
+
"size": 318742,
|
|
1141
|
+
"mtime": "2024-03-18T20:45:01.328Z"
|
|
1142
|
+
}
|
|
1143
|
+
},
|
|
1144
|
+
"headers": {
|
|
1145
|
+
"host": "localhost:3012",
|
|
1146
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
1147
|
+
"sec-fetch-site": "same-origin",
|
|
1148
|
+
"accept-language": "en-US,en;q=0.9",
|
|
1149
|
+
"accept-encoding": "gzip, deflate",
|
|
1150
|
+
"sec-fetch-mode": "navigate",
|
|
1151
|
+
"content-type": "multipart/form-data; boundary=----WebKitFormBoundaryAzquNdwdvTjj9ArR",
|
|
1152
|
+
"origin": "http://localhost:3012",
|
|
1153
|
+
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15",
|
|
1154
|
+
"referer": "http://localhost:3012/upload.html",
|
|
1155
|
+
"upgrade-insecure-requests": "1",
|
|
1156
|
+
"content-length": "319132",
|
|
1157
|
+
"connection": "keep-alive",
|
|
1158
|
+
"sec-fetch-dest": "document"
|
|
1159
|
+
},
|
|
1160
|
+
"cookies": {},
|
|
1161
|
+
"query": {
|
|
1162
|
+
"pretty": "1"
|
|
1163
|
+
},
|
|
1164
|
+
"params": {
|
|
1165
|
+
"key1": "value1",
|
|
1166
|
+
"key2": "value2"
|
|
1167
|
+
},
|
|
1168
|
+
"response": {
|
|
1169
|
+
"code": 200,
|
|
1170
|
+
"status": "OK",
|
|
1171
|
+
"headers": {
|
|
1172
|
+
"content-type": "application/json",
|
|
1173
|
+
"x-joetest": "9876",
|
|
1174
|
+
"server": "Test Server 1.0",
|
|
1175
|
+
"x-200": "YUP BRO",
|
|
1176
|
+
"content-length": "261",
|
|
1177
|
+
"content-encoding": "gzip"
|
|
1178
|
+
},
|
|
1179
|
+
"raw": "{\n\t\"code\": 0,\n\t\"query\": {\n\t\t\"pretty\": \"1\"\n\t},\n\t\"params\": {\n\t\t\"key1\": \"value1\",\n\t\t\"key2\": \"value2\"\n\t},\n\t\"cookies\": {},\n\t\"files\": {\n\t\t\"file1\": {\n\t\t\t\"path\": \"/var/folders/11/r_0sz6s13cx1jn68l4m90zfr0000gn/T/f92cd259263698f0e19581400.LBM\",\n\t\t\t\"type\": \"application/octet-stream\",\n\t\t\t\"name\": \"V04.LBM\",\n\t\t\t\"size\": 318742,\n\t\t\t\"mtime\": \"2024-03-18T20:45:01.328Z\"\n\t\t}\n\t}\n}\n"
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
```
|
|
1183
|
+
|
|
1184
|
+
As you can see, in addition to all the information logged with [http_log_requests](#http_log_requests), the `data` column now includes even more detail. Here is the full list of all JSON properties and their descriptions, logged with [http_log_request_details](#http_log_request_details) enabled:
|
|
1185
|
+
|
|
1186
|
+
| Property | Type | Description |
|
|
1187
|
+
|----------|------|-------------|
|
|
1188
|
+
| `id` | String | The internal ID for the request. |
|
|
1189
|
+
| `proto` | String | The protocol of the request (`http` or `https`). |
|
|
1190
|
+
| `ip` | String | The first non-internal IP address (see [args.ip](#argsip)). |
|
|
1191
|
+
| `ips` | Array | All the client IPs as an array (includes those from proxy headers). |
|
|
1192
|
+
| `port` | Number | Which port number the request came in on. |
|
|
1193
|
+
| `socket` | String | The unique ID of the socket which served the request. |
|
|
1194
|
+
| `perf` | Object | Performance metrics, in [pixl-perf](https://github.com/jhuckaby/pixl-perf) format. |
|
|
1195
|
+
| `files` | Object | If applicable, metadata about all file uploads (file names, sizes, types, and dates). |
|
|
1196
|
+
| `headers` | Object | All the HTTP request headers in key/value format (lower-cased keys). |
|
|
1197
|
+
| `cookies` | Object | Cookies from the request, parsed and in key/value form. |
|
|
1198
|
+
| `query` | Object | The query string from the request URL parsed into key/value pairs. |
|
|
1199
|
+
| `params` | Object | Key/value pairs from the request, i.e. parsed JSON or form POST data. |
|
|
1200
|
+
| `params.raw` | String | If applicable, the raw request body as a UTF-8 string (see below). |
|
|
1201
|
+
| `response` | Object | Details about the HTTP response sent to the client. |
|
|
1202
|
+
| `response.code` | Number | The HTTP response code (e.g. `200`). |
|
|
1203
|
+
| `response.status` | String | The HTTP response status (e.g. `OK`). |
|
|
1204
|
+
| `response.headers` | Object | All the HTTP response headers sent to the client (lower-cased keys). |
|
|
1205
|
+
| `response.raw` | String | If applicable, the raw response body as a UTF-8 string (see below). |
|
|
1206
|
+
|
|
1207
|
+
The raw request and response content will only be logged in certain cases:
|
|
1208
|
+
|
|
1209
|
+
- If the request was a JSON POST, then the parsed JSON document will be in the `params` object.
|
|
1210
|
+
- If the request was a non-JSON POST, but the content is recognized to be text, then the raw request body will be in `params.raw` as a UTF-8 string.
|
|
1211
|
+
- If the request was a form post, then the key/value pairs will be in the `params` object.
|
|
1212
|
+
- If the request contained file uploads, they will be summarized in the `files` object (see above for example).
|
|
1213
|
+
- If the response is recognized as text, it will be included in `response.raw` as a UTF-8 string.
|
|
1214
|
+
- If the response is non-text (binary), the raw content will not be included.
|
|
1215
|
+
- If the response is a stream, it will not be included.
|
|
1216
|
+
|
|
1093
1217
|
## Performance Threshold Logging
|
|
1094
1218
|
|
|
1095
1219
|
In addition to [Transaction Logging](#transaction-logging), pixl-server-web can also log performance metrics for certain requests, if the total request elapsed time meets or exceeds a custom threshold. This allows you to log only "slow" requests, i.e. those possibly requiring investigation. This is an optional feature which is disabled by default. To enable it, set the [http_log_perf](#http_log_perf) configuration property to `true`, and then set the [http_perf_threshold_ms](#http_perf_threshold_ms) property to the desired logging threshold in milliseconds. Example:
|
|
1096
1220
|
|
|
1097
|
-
```
|
|
1221
|
+
```json
|
|
1098
1222
|
{
|
|
1099
1223
|
"http_log_perf": true,
|
|
1100
1224
|
"http_perf_threshold_ms": 100
|
|
@@ -1122,7 +1246,7 @@ The log columns are configurable in [pixl-server](https://github.com/jhuckaby/pi
|
|
|
1122
1246
|
|
|
1123
1247
|
The `data` column is a JSON document containing various bits of additional information about the request, including the performance metrics. Here is a formatted example:
|
|
1124
1248
|
|
|
1125
|
-
```
|
|
1249
|
+
```json
|
|
1126
1250
|
{
|
|
1127
1251
|
"id": "r4",
|
|
1128
1252
|
"proto": "http",
|
|
@@ -1176,7 +1300,7 @@ The performance threshold system retroactively adjusts the log to represent the
|
|
|
1176
1300
|
|
|
1177
1301
|
To include a partial or complete [Node.js Diagnostic Report](https://nodejs.org/docs/latest/api/report.html) in your performance log data, set the [http_perf_report](#http_perf_report) configuration property. For a full report, set it to `true`:
|
|
1178
1302
|
|
|
1179
|
-
```
|
|
1303
|
+
```json
|
|
1180
1304
|
{
|
|
1181
1305
|
"http_perf_report": true
|
|
1182
1306
|
}
|
|
@@ -1184,7 +1308,7 @@ To include a partial or complete [Node.js Diagnostic Report](https://nodejs.org/
|
|
|
1184
1308
|
|
|
1185
1309
|
However, please note that this is *very* verbose. For a partial report, you can set it to an array of report keys to include. Example:
|
|
1186
1310
|
|
|
1187
|
-
```
|
|
1311
|
+
```json
|
|
1188
1312
|
{
|
|
1189
1313
|
"http_perf_report": ["uvthreadResourceUsage"]
|
|
1190
1314
|
}
|
|
@@ -1235,12 +1359,12 @@ See the [pixl-perf](https://www.github.com/jhuckaby/pixl-perf) documentation for
|
|
|
1235
1359
|
The web server keeps internal statistics including all open sockets, all active and recently completed requests, and performance metrics. You can query for these by calling the `getStats()` method on the web server component. Example:
|
|
1236
1360
|
|
|
1237
1361
|
```js
|
|
1238
|
-
|
|
1362
|
+
let stats = server.WebServer.getStats();
|
|
1239
1363
|
```
|
|
1240
1364
|
|
|
1241
1365
|
The result is an object in this format:
|
|
1242
1366
|
|
|
1243
|
-
```
|
|
1367
|
+
```json
|
|
1244
1368
|
{
|
|
1245
1369
|
"server": {
|
|
1246
1370
|
"uptime": 80,
|
|
@@ -1496,13 +1620,13 @@ See the [https_header_detect](#https_header_detect) configuration property for a
|
|
|
1496
1620
|
To build a URL that points at the current server, call `getSelfURL()` and pass in the `args.request` object. This will produce a URL using the same protocol as the request (HTTP or HTTPS), the same hostname used on the request, and the port number if applicable. By default, the URL will point to the root path (`/`). Example:
|
|
1497
1621
|
|
|
1498
1622
|
```js
|
|
1499
|
-
|
|
1623
|
+
let url = server.WebServer.getSelfURL(args.request);
|
|
1500
1624
|
```
|
|
1501
1625
|
|
|
1502
1626
|
You can optionally pass in a URI path as the second argument. For example, to build a URL to the exact request URI that came in, pass in `args.request.url` as the second argument:
|
|
1503
1627
|
|
|
1504
1628
|
```js
|
|
1505
|
-
|
|
1629
|
+
let url = server.WebServer.getSelfURL(args.request, args.request.url);
|
|
1506
1630
|
```
|
|
1507
1631
|
|
|
1508
1632
|
## Custom Method Handlers
|
|
@@ -1531,7 +1655,7 @@ server.WebServer.addMethodHandler( "OPTIONS", "CORS Preflight", function(args, c
|
|
|
1531
1655
|
|
|
1532
1656
|
Here are instructions for using [Let's Encrypt](https://letsencrypt.org/) SSL certificates with pixl-server-web, specifically how to get your certificate issued and how to setup automatic renewal.
|
|
1533
1657
|
|
|
1534
|
-
The first thing you should do is make sure your server has a public IP address, and point your domain name to it using a DNS "A" record. For these examples
|
|
1658
|
+
The first thing you should do is make sure your server has a public IP address, and point your domain name to it using a DNS "A" record. For these examples we will be using the domain `mydomain.com`.
|
|
1535
1659
|
|
|
1536
1660
|
Next, you will need to manually install [certbot](https://certbot.eff.org) on your server. The easiest way to do this is to use the wrapper script [certbot-auto](https://certbot.eff.org/docs/install.html#certbot-auto), like this:
|
|
1537
1661
|
|
|
@@ -1541,10 +1665,10 @@ curl -s https://dl.eff.org/certbot-auto > /usr/local/bin/certbot-auto
|
|
|
1541
1665
|
chmod a+x /usr/local/bin/certbot-auto
|
|
1542
1666
|
```
|
|
1543
1667
|
|
|
1544
|
-
We'll be using the [Webroot](https://certbot.eff.org/docs/using.html#webroot) method for authorization. Make sure you have a web server running on your server and listening on port 80 (only plain HTTP is required at this point). Assuming your web server's document root path is `/
|
|
1668
|
+
We'll be using the [Webroot](https://certbot.eff.org/docs/using.html#webroot) method for authorization. Make sure you have a web server running on your server and listening on port 80 (only plain HTTP is required at this point). Assuming your web server's document root path is `/let/www/html` issue this command:
|
|
1545
1669
|
|
|
1546
1670
|
```sh
|
|
1547
|
-
/usr/local/bin/certbot-auto certonly --webroot -w /
|
|
1671
|
+
/usr/local/bin/certbot-auto certonly --webroot -w /let/www/html -d mydomain.com
|
|
1548
1672
|
```
|
|
1549
1673
|
|
|
1550
1674
|
If you need certificates for multiple subdomains, you can repeat the `-d` flag, e.g. `-d mydomain.com -d www.mydomain.com`.
|
|
@@ -1598,7 +1722,7 @@ Toss that command into a shell script in `/etc/cron.daily/` and it'll run daily
|
|
|
1598
1722
|
/usr/local/bin/certbot-auto renew --post-hook "/opt/myapp/bin/control.sh restart" >/dev/null 2>&1
|
|
1599
1723
|
```
|
|
1600
1724
|
|
|
1601
|
-
Certbot produces its own log file here: `/
|
|
1725
|
+
Certbot produces its own log file here: `/let/log/letsencrypt/letsencrypt.log`
|
|
1602
1726
|
|
|
1603
1727
|
## Request Max Dump
|
|
1604
1728
|
|
|
@@ -1612,30 +1736,32 @@ To enable this feature, set the [http_req_max_dump_enabled](#http_req_max_dump_e
|
|
|
1612
1736
|
|
|
1613
1737
|
```json
|
|
1614
1738
|
"http_req_max_dump_enabled": true,
|
|
1615
|
-
"http_req_max_dump_dir": "/
|
|
1739
|
+
"http_req_max_dump_dir": "/let/log/web-server-dumps",
|
|
1616
1740
|
"http_req_max_dump_debounce": 10
|
|
1617
1741
|
```
|
|
1618
1742
|
|
|
1619
|
-
This would generate dump files in the `/
|
|
1743
|
+
This would generate dump files in the `/let/log/web-server-dumps` directory every 10 seconds, while one or more maximum limits are maxed out.
|
|
1620
1744
|
|
|
1621
|
-
The dump files themselves are in JSON format, and contain everything from the [Stats API](#stats), as well as a list of all active and pending requests. For each request, the following
|
|
1745
|
+
The dump files themselves are in JSON format, and contain everything from the [Stats API](#stats), as well as a list of all active and pending requests. For each request, an object like the following is provided:
|
|
1622
1746
|
|
|
1623
1747
|
```json
|
|
1624
|
-
|
|
1625
|
-
"
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
"
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
"
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1748
|
+
{
|
|
1749
|
+
"r2945": {
|
|
1750
|
+
"uri": "/api/test/sleep?ms=1",
|
|
1751
|
+
"ip": "127.0.0.1",
|
|
1752
|
+
"ips": [
|
|
1753
|
+
"127.0.0.1"
|
|
1754
|
+
],
|
|
1755
|
+
"headers": {
|
|
1756
|
+
"accept-encoding": "gzip, deflate, br",
|
|
1757
|
+
"user-agent": "Mozilla/5.0; wperf/1.0.4",
|
|
1758
|
+
"host": "localhost:3012",
|
|
1759
|
+
"connection": "keep-alive"
|
|
1760
|
+
},
|
|
1761
|
+
"state": "writing",
|
|
1762
|
+
"date": 1644617758.688,
|
|
1763
|
+
"elapsed": 0.009999990463256836
|
|
1764
|
+
}
|
|
1639
1765
|
}
|
|
1640
1766
|
```
|
|
1641
1767
|
|
package/lib/response.js
CHANGED
|
@@ -102,6 +102,12 @@ module.exports = class Response {
|
|
|
102
102
|
headers['Content-Length'] = body.length;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
// copy stuff into args for detail logging
|
|
106
|
+
if (this.logRequestDetails) {
|
|
107
|
+
args.resp_body = body;
|
|
108
|
+
args.resp_headers = headers;
|
|
109
|
+
}
|
|
110
|
+
|
|
105
111
|
// track stream bytes, if applicable
|
|
106
112
|
var meter = null;
|
|
107
113
|
|
|
@@ -322,16 +328,63 @@ module.exports = class Response {
|
|
|
322
328
|
|
|
323
329
|
// write to access log
|
|
324
330
|
if (this.logRequests && args.request.url.match(this.regexLogRequests)) {
|
|
325
|
-
|
|
331
|
+
var data = {
|
|
326
332
|
id: args.id,
|
|
327
333
|
proto: args.request.headers['ssl'] ? 'https' : socket_data.proto,
|
|
334
|
+
ip: args.ip,
|
|
328
335
|
ips: args.ips,
|
|
329
336
|
port: socket_data.port,
|
|
330
337
|
socket: socket_data.id,
|
|
331
|
-
host: args.request.headers['host'] || '',
|
|
332
|
-
ua: args.request.headers['user-agent'] || '',
|
|
333
338
|
perf: metrics
|
|
334
|
-
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
if (this.logRequestDetails) {
|
|
342
|
+
// extra transaction log details
|
|
343
|
+
data.files = args.files || {};
|
|
344
|
+
data.headers = args.request.headers || {};
|
|
345
|
+
data.cookies = args.cookies || {};
|
|
346
|
+
data.query = args.query || {};
|
|
347
|
+
data.params = Object.assign( {}, args.params || {} );
|
|
348
|
+
|
|
349
|
+
if (data.params.raw && data.params.raw.buffer && data.params.raw.toString) {
|
|
350
|
+
if (args.request.headers['content-type'] && args.request.headers['content-type'].match(/(text|javascript|json|xml)/)) {
|
|
351
|
+
data.params.raw = data.params.raw.toString('utf8');
|
|
352
|
+
}
|
|
353
|
+
else data.params.raw = '(Binary Buffer)';
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
data.response = {
|
|
357
|
+
code: args.http_code,
|
|
358
|
+
status: args.http_status,
|
|
359
|
+
headers: {}
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
if (args.resp_headers) {
|
|
363
|
+
for (var key in args.resp_headers) {
|
|
364
|
+
data.response.headers[ key.toLowerCase() ] = args.resp_headers[key];
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (args.resp_body && args.resp_body.pipe) {
|
|
369
|
+
data.response.raw = '(Stream)';
|
|
370
|
+
}
|
|
371
|
+
else if (args.resp_body && args.resp_body.buffer && args.resp_body.toString) {
|
|
372
|
+
if (data.response.headers && data.response.headers['content-type'] && data.response.headers['content-type'].match(/(text|javascript|json|xml)/)) {
|
|
373
|
+
data.response.raw = args.resp_body.toString('utf8');
|
|
374
|
+
}
|
|
375
|
+
else data.response.raw = '(Binary Buffer)';
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
delete args.resp_body;
|
|
379
|
+
delete args.resp_headers;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
// standard transaction log
|
|
383
|
+
data.host = args.request.headers['host'] || '';
|
|
384
|
+
data.ua = args.request.headers['user-agent'] || '';
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
this.logTransaction( 'HTTP ' + args.http_code + ' ' + args.http_status, args.request.url, data );
|
|
335
388
|
}
|
|
336
389
|
|
|
337
390
|
// optional threshold-based perf log
|
package/package.json
CHANGED
package/web_server.js
CHANGED
|
@@ -47,6 +47,7 @@ module.exports = Class({
|
|
|
47
47
|
"http_enable_brotli": false,
|
|
48
48
|
"http_default_acl": ['127.0.0.1', '10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '::1/128', 'fd00::/8', '169.254.0.0/16', 'fe80::/10'],
|
|
49
49
|
"http_log_requests": false,
|
|
50
|
+
"http_log_request_details": false,
|
|
50
51
|
"http_log_perf": false,
|
|
51
52
|
"http_perf_threshold_ms": 100,
|
|
52
53
|
"http_perf_report": false,
|
|
@@ -102,6 +103,7 @@ class WebServer extends Component {
|
|
|
102
103
|
this.regexTextContent = new RegExp( this.config.get('http_regex_text'), "i" );
|
|
103
104
|
this.regexJSONContent = new RegExp( this.config.get('http_regex_json'), "i" );
|
|
104
105
|
this.logRequests = this.config.get('http_log_requests');
|
|
106
|
+
this.logRequestDetails = this.config.get('http_log_request_details');
|
|
105
107
|
this.regexLogRequests = this.logRequests ? (new RegExp( this.config.get('http_regex_log') || '.+' )) : null;
|
|
106
108
|
this.logPerfEnabled = this.config.get('http_log_perf');
|
|
107
109
|
this.logPerfThreshold = this.config.get('http_perf_threshold_ms');
|