jsgui3-server 0.0.146 → 0.0.147
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 +16 -0
- package/docs/agent-development-guide.md +92 -9
- package/docs/books/jsgui3-mvvm-fullstack/00-overview.md +17 -0
- package/docs/books/jsgui3-mvvm-fullstack/01-stack-map.md +25 -0
- package/docs/books/jsgui3-mvvm-fullstack/02-control-lifecycle.md +32 -0
- package/docs/books/jsgui3-mvvm-fullstack/03-mvvm-basics.md +57 -0
- package/docs/books/jsgui3-mvvm-fullstack/04-bindings-and-validation.md +51 -0
- package/docs/books/jsgui3-mvvm-fullstack/05-full-stack-example.md +50 -0
- package/docs/books/jsgui3-mvvm-fullstack/06-testing.md +23 -0
- package/docs/books/jsgui3-mvvm-fullstack/07-troubleshooting.md +20 -0
- package/docs/books/jsgui3-mvvm-fullstack/08-agent-playbooks.md +30 -0
- package/docs/books/jsgui3-mvvm-fullstack/README.md +30 -0
- package/docs/comprehensive-documentation.md +145 -34
- package/docs/diagrams/jsgui3-progress-update.svg +181 -0
- package/examples/controls/18) window, observable bindRemote/README.md +28 -0
- package/examples/controls/18) window, observable bindRemote/check.js +144 -0
- package/examples/controls/18) window, observable bindRemote/client.js +387 -0
- package/examples/controls/18) window, observable bindRemote/server.js +107 -0
- package/package.json +4 -4
- package/publishers/http-webpage-publisher.js +39 -16
- package/publishers/http-webpageorsite-publisher.js +48 -35
- package/server.js +199 -185
- package/tests/server-publish-observable.test.js +99 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
const {each, Router, tof} = require('jsgui3-html');
|
|
4
|
+
const { each, Router, tof } = require('jsgui3-html');
|
|
5
5
|
const HTTP_Publisher = require('./http-publisher');
|
|
6
|
-
const {obs} = require('fnl');
|
|
6
|
+
const { obs } = require('fnl');
|
|
7
7
|
|
|
8
8
|
// The Webpage bundler should be able to come up with the compiled JS and CSS, maybe even a favicon.
|
|
9
9
|
|
|
@@ -97,9 +97,9 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
97
97
|
constructor(spec) {
|
|
98
98
|
super(spec);
|
|
99
99
|
|
|
100
|
-
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
101
|
-
this.style_config = spec.style || {};
|
|
102
|
-
this.bundler_config = spec.bundler || {};
|
|
100
|
+
if (spec.debug !== undefined) this.debug = spec.debug;
|
|
101
|
+
this.style_config = spec.style || {};
|
|
102
|
+
this.bundler_config = spec.bundler || {};
|
|
103
103
|
|
|
104
104
|
// But then some properties to do with the js client(s?) file path.
|
|
105
105
|
|
|
@@ -109,37 +109,37 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
109
109
|
// js_client_file_path ??? client_js_file_path???
|
|
110
110
|
|
|
111
111
|
let src_path_client_js;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
if (spec.disk_path_client_js) {
|
|
113
|
+
src_path_client_js = spec.disk_path_client_js;
|
|
114
|
+
} else if (spec.src_path_client_js) {
|
|
115
|
+
src_path_client_js = spec.src_path_client_js;
|
|
116
|
+
} else if (spec.source_path_client_js) {
|
|
117
|
+
src_path_client_js = spec.source_path_client_js;
|
|
118
|
+
};
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
// or src_path_client_js as well...
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
Object.defineProperty(this, 'disk_path_client_js', { get: () => src_path_client_js, set: (value) => src_path_client_js = value });
|
|
123
|
+
Object.defineProperty(this, 'src_path_client_js', { get: () => src_path_client_js, set: (value) => src_path_client_js = value });
|
|
124
|
+
Object.defineProperty(this, 'source_path_client_js', { get: () => src_path_client_js, set: (value) => src_path_client_js = value });
|
|
125
125
|
|
|
126
126
|
|
|
127
127
|
// But then need to have some things that get it ready on this level...
|
|
128
128
|
|
|
129
129
|
// Maybe need a get_ready (async or obs) function....
|
|
130
130
|
|
|
131
|
-
this.js_bundler = new JS_Bundler({
|
|
132
|
-
'debug': this.debug || false,
|
|
133
|
-
'style': this.style_config,
|
|
134
|
-
'bundler': this.bundler_config
|
|
135
|
-
});
|
|
131
|
+
this.js_bundler = new JS_Bundler({
|
|
132
|
+
'debug': this.debug || false,
|
|
133
|
+
'style': this.style_config,
|
|
134
|
+
'bundler': this.bundler_config
|
|
135
|
+
});
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
async get_ready() {
|
|
141
141
|
|
|
142
|
-
const {js_bundler} = this;
|
|
142
|
+
const { js_bundler } = this;
|
|
143
143
|
//await super.get_ready(); // Does not have one
|
|
144
144
|
|
|
145
145
|
// Then bundle (extract (process) everything in and referenced by the JS file (s) into a bundle object)
|
|
@@ -158,20 +158,33 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
158
158
|
// Single js client for whole website??? Could work, not so sure.
|
|
159
159
|
// Appropriate defalt setting (using v explicit classes) will help it to work.
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
//
|
|
166
|
-
|
|
161
|
+
const { src_path_client_js } = this;
|
|
162
|
+
|
|
163
|
+
console.log('[HTTP_Webpageorsite_Publisher] get_ready called, src_path_client_js:', src_path_client_js);
|
|
164
|
+
|
|
165
|
+
// Skip bundling if no client.js path is provided
|
|
166
|
+
// This allows Server.serve() to work with SSR-only controls
|
|
167
|
+
if (!src_path_client_js) {
|
|
168
|
+
console.log('[HTTP_Webpageorsite_Publisher] No src_path_client_js provided - skipping JS bundling');
|
|
169
|
+
// Return an empty bundle with minimal CSS and JS
|
|
170
|
+
const empty_bundle = new Bundle();
|
|
171
|
+
empty_bundle.push({
|
|
172
|
+
type: 'CSS',
|
|
173
|
+
extension: 'css',
|
|
174
|
+
text: '/* No client CSS */'
|
|
175
|
+
});
|
|
176
|
+
empty_bundle.push({
|
|
177
|
+
type: 'JavaScript',
|
|
178
|
+
extension: 'js',
|
|
179
|
+
text: '/* No client JS - SSR only */'
|
|
180
|
+
});
|
|
181
|
+
return empty_bundle;
|
|
182
|
+
}
|
|
167
183
|
|
|
168
184
|
// The js_bundler may need to operate in 'debug' mode.
|
|
169
|
-
|
|
170
185
|
const js_bundler_res = await js_bundler.bundle(src_path_client_js);
|
|
171
186
|
// Should also get the CSS from it....
|
|
172
187
|
|
|
173
|
-
|
|
174
|
-
|
|
175
188
|
//console.log('js_bundler_res', js_bundler_res);
|
|
176
189
|
|
|
177
190
|
// Res of length 2 - with a css item and a js item.
|
|
@@ -182,7 +195,7 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
182
195
|
|
|
183
196
|
const css_item = bundle._arr.find((item) => item.type === 'CSS');
|
|
184
197
|
const js_item = bundle._arr.find((item) => item.type === 'JavaScript');
|
|
185
|
-
|
|
198
|
+
|
|
186
199
|
if (css_item && js_item) {
|
|
187
200
|
|
|
188
201
|
return bundle;
|
|
@@ -261,7 +274,7 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
261
274
|
// This part here is just getting ready to publish.
|
|
262
275
|
|
|
263
276
|
|
|
264
|
-
|
|
277
|
+
|
|
265
278
|
|
|
266
279
|
|
|
267
280
|
|
|
@@ -312,7 +325,7 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
312
325
|
console.trace();
|
|
313
326
|
throw 'stop';
|
|
314
327
|
|
|
315
|
-
|
|
328
|
+
|
|
316
329
|
|
|
317
330
|
} else {
|
|
318
331
|
console.log('js_bundler_res', js_bundler_res);
|
|
@@ -330,7 +343,7 @@ class HTTP_Webpageorsite_Publisher extends HTTP_Publisher {
|
|
|
330
343
|
|
|
331
344
|
|
|
332
345
|
|
|
333
|
-
|
|
346
|
+
|
|
334
347
|
|
|
335
348
|
|
|
336
349
|
|
package/server.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const jsgui = require('jsgui3-html'),
|
|
2
2
|
http = require('http'),
|
|
3
3
|
https = require('https'),
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
{ prop, read_only } = require('obext'),
|
|
5
|
+
fs = require('fs'),
|
|
6
6
|
Resource = jsgui.Resource,
|
|
7
7
|
Server_Resource_Pool = require('./resources/server-resource-pool'),
|
|
8
8
|
Router = jsgui.Router,
|
|
@@ -15,7 +15,7 @@ const jsgui = require('jsgui3-html'),
|
|
|
15
15
|
tof
|
|
16
16
|
} = jsgui;
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
const lib_path = require('path');
|
|
20
20
|
const Web_Admin_Page_Control = require('./controls/page/admin');
|
|
21
21
|
const Web_Admin_Panel_Control = require('./controls/panel/admin');
|
|
@@ -24,6 +24,7 @@ const HTTP_Website_Publisher = require('./publishers/http-website-publisher');
|
|
|
24
24
|
const Webpage = require('./website/webpage');
|
|
25
25
|
const HTTP_Webpage_Publisher = require('./publishers/http-webpage-publisher');
|
|
26
26
|
const HTTP_Function_Publisher = require('./publishers/http-function-publisher');
|
|
27
|
+
const HTTP_Observable_Publisher = require('./publishers/http-observable-publisher');
|
|
27
28
|
|
|
28
29
|
const Static_Route_HTTP_Responder = require('./http/responders/static/Static_Route_HTTP_Responder');
|
|
29
30
|
|
|
@@ -45,23 +46,23 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
|
|
48
|
-
if (spec.debug !== undefined) {
|
|
49
|
-
this.debug = spec.debug;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const style_config = spec.style;
|
|
53
|
-
const bundler_config = spec.bundler;
|
|
49
|
+
if (spec.debug !== undefined) {
|
|
50
|
+
this.debug = spec.debug;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const style_config = spec.style;
|
|
54
|
+
const bundler_config = spec.bundler;
|
|
54
55
|
|
|
55
56
|
// or src_path_client_js as well...
|
|
56
57
|
|
|
57
|
-
Object.defineProperty(this, 'disk_path_client_js', {get: () => disk_path_client_js, set: (value) => disk_path_client_js = value});
|
|
58
|
-
Object.defineProperty(this, 'src_path_client_js', {get: () => disk_path_client_js, set: (value) => disk_path_client_js = value});
|
|
59
|
-
Object.defineProperty(this, 'source_path_client_js', {get: () => disk_path_client_js, set: (value) => disk_path_client_js = value});
|
|
58
|
+
Object.defineProperty(this, 'disk_path_client_js', { get: () => disk_path_client_js, set: (value) => disk_path_client_js = value });
|
|
59
|
+
Object.defineProperty(this, 'src_path_client_js', { get: () => disk_path_client_js, set: (value) => disk_path_client_js = value });
|
|
60
|
+
Object.defineProperty(this, 'source_path_client_js', { get: () => disk_path_client_js, set: (value) => disk_path_client_js = value });
|
|
60
61
|
|
|
61
62
|
let Ctrl = spec.Ctrl || undefined
|
|
62
|
-
Object.defineProperty(this, 'Ctrl', {get: () => Ctrl, set: value => Ctrl = value})
|
|
63
|
+
Object.defineProperty(this, 'Ctrl', { get: () => Ctrl, set: value => Ctrl = value })
|
|
63
64
|
let name = spec.name || undefined;
|
|
64
|
-
Object.defineProperty(this, 'name', {get: () => name, set: value => name = value})
|
|
65
|
+
Object.defineProperty(this, 'name', { get: () => name, set: value => name = value })
|
|
65
66
|
this.__type_name = __type_name || 'server';
|
|
66
67
|
const resource_pool = this.resource_pool = new Server_Resource_Pool({
|
|
67
68
|
'access': {
|
|
@@ -92,20 +93,20 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
92
93
|
if (Ctrl) {
|
|
93
94
|
|
|
94
95
|
|
|
95
|
-
const wp_app = new Webpage({content: Ctrl});
|
|
96
|
+
const wp_app = new Webpage({ content: Ctrl });
|
|
97
|
+
|
|
98
|
+
const opts_wp_publisher = {
|
|
99
|
+
'webpage': wp_app
|
|
100
|
+
|
|
101
|
+
};
|
|
102
|
+
if (bundler_config !== undefined) opts_wp_publisher.bundler = bundler_config;
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
if (bundler_config !== undefined) opts_wp_publisher.bundler = bundler_config;
|
|
102
|
-
|
|
103
|
-
if (this.debug) {
|
|
104
|
-
opts_wp_publisher.debug = this.debug;
|
|
105
|
-
}
|
|
104
|
+
if (this.debug) {
|
|
105
|
+
opts_wp_publisher.debug = this.debug;
|
|
106
|
+
}
|
|
106
107
|
|
|
107
|
-
if (disk_path_client_js) opts_wp_publisher.src_path_client_js = disk_path_client_js;
|
|
108
|
-
if (style_config !== undefined) opts_wp_publisher.style = style_config;
|
|
108
|
+
if (disk_path_client_js) opts_wp_publisher.src_path_client_js = disk_path_client_js;
|
|
109
|
+
if (style_config !== undefined) opts_wp_publisher.style = style_config;
|
|
109
110
|
|
|
110
111
|
|
|
111
112
|
|
|
@@ -122,7 +123,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
122
123
|
|
|
123
124
|
for (const bundle_item of wp_ready_res._arr) {
|
|
124
125
|
//console.log('Object.keys(bundle_item)', Object.keys(bundle_item));
|
|
125
|
-
const {type, extension, text, route, response_buffers, response_headers} = bundle_item;
|
|
126
|
+
const { type, extension, text, route, response_buffers, response_headers } = bundle_item;
|
|
126
127
|
const bundle_item_http_responder = new Static_Route_HTTP_Responder(bundle_item);
|
|
127
128
|
|
|
128
129
|
|
|
@@ -165,18 +166,18 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
165
166
|
const ws_app = this.app = this.website = new Website(opts_website);
|
|
166
167
|
// Be able to treat Webpage as an app?
|
|
167
168
|
|
|
168
|
-
const opts_ws_publisher = {
|
|
169
|
-
'website': ws_app
|
|
170
|
-
};
|
|
171
|
-
if (disk_path_client_js) {
|
|
172
|
-
opts_ws_publisher.disk_path_client_js = disk_path_client_js;
|
|
173
|
-
}
|
|
174
|
-
if (bundler_config !== undefined) {
|
|
175
|
-
opts_ws_publisher.bundler = bundler_config;
|
|
176
|
-
}
|
|
177
|
-
if (style_config !== undefined) {
|
|
178
|
-
opts_ws_publisher.style = style_config;
|
|
179
|
-
}
|
|
169
|
+
const opts_ws_publisher = {
|
|
170
|
+
'website': ws_app
|
|
171
|
+
};
|
|
172
|
+
if (disk_path_client_js) {
|
|
173
|
+
opts_ws_publisher.disk_path_client_js = disk_path_client_js;
|
|
174
|
+
}
|
|
175
|
+
if (bundler_config !== undefined) {
|
|
176
|
+
opts_ws_publisher.bundler = bundler_config;
|
|
177
|
+
}
|
|
178
|
+
if (style_config !== undefined) {
|
|
179
|
+
opts_ws_publisher.style = style_config;
|
|
180
|
+
}
|
|
180
181
|
const ws_publisher = new HTTP_Website_Publisher(opts_ws_publisher);
|
|
181
182
|
this._ws_publisher = ws_publisher;
|
|
182
183
|
ws_publisher.on('ready', () => {
|
|
@@ -191,7 +192,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
191
192
|
});
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
|
|
195
|
+
|
|
195
196
|
Object.defineProperty(this, 'router', { get: () => server_router })
|
|
196
197
|
}
|
|
197
198
|
|
|
@@ -200,7 +201,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
200
201
|
// Possibly ensure it exists.
|
|
201
202
|
//const fn_publisher = this.function_publisher;
|
|
202
203
|
//fn_publisher.add(name, fn);
|
|
203
|
-
const fpub = new HTTP_Function_Publisher({name, fn});
|
|
204
|
+
const fpub = new HTTP_Function_Publisher({ name, fn });
|
|
204
205
|
|
|
205
206
|
this.function_publishers = this.function_publishers || [];
|
|
206
207
|
this.function_publishers.push(fpub);
|
|
@@ -208,11 +209,24 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
208
209
|
this.server_router.set_route('/api/' + name, fpub, fpub.handle_http);
|
|
209
210
|
}
|
|
210
211
|
|
|
212
|
+
publish_observable(route, obs, options = {}) {
|
|
213
|
+
const publisher = new HTTP_Observable_Publisher({
|
|
214
|
+
obs,
|
|
215
|
+
...options
|
|
216
|
+
});
|
|
217
|
+
this.server_router.set_route(route, publisher, publisher.handle_http);
|
|
218
|
+
return publisher;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
publishObservable(route, obs, options) {
|
|
222
|
+
return this.publish_observable(route, obs, options);
|
|
223
|
+
}
|
|
224
|
+
|
|
211
225
|
|
|
212
226
|
get resource_names() {
|
|
213
227
|
return this.resource_pool.resource_names;
|
|
214
228
|
}
|
|
215
|
-
'start'
|
|
229
|
+
'start'(port, callback, fnProcessRequest) {
|
|
216
230
|
if (tof(port) !== 'number') {
|
|
217
231
|
console.log('Invalid port:', port);
|
|
218
232
|
console.trace();
|
|
@@ -233,7 +247,7 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
233
247
|
if (err) {
|
|
234
248
|
callback(err);
|
|
235
249
|
} else {
|
|
236
|
-
|
|
250
|
+
// NEW: Filter addresses by allowed_addresses if specified.
|
|
237
251
|
let arr_ipv4_addresses = [];
|
|
238
252
|
each(net, (arr_addresses, name) => {
|
|
239
253
|
each(arr_addresses, (obj_address) => {
|
|
@@ -245,33 +259,33 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
245
259
|
if (this.allowed_addresses && this.allowed_addresses.length) {
|
|
246
260
|
arr_ipv4_addresses = arr_ipv4_addresses.filter(a => this.allowed_addresses.indexOf(a) > -1);
|
|
247
261
|
}
|
|
248
|
-
arr_ipv4_addresses = [...new Set(arr_ipv4_addresses)];
|
|
249
|
-
console.log('IPv4 addresses to bind:', arr_ipv4_addresses);
|
|
250
|
-
let num_to_start = arr_ipv4_addresses.length;
|
|
251
|
-
let started_count = 0;
|
|
252
|
-
let last_error = null;
|
|
253
|
-
let ready_raised = false;
|
|
254
|
-
if (num_to_start === 0) {
|
|
255
|
-
callback('No allowed network interfaces found.');
|
|
256
|
-
return;
|
|
257
|
-
}
|
|
258
|
-
const finalize_start = (err) => {
|
|
259
|
-
if (num_to_start !== 0) return;
|
|
260
|
-
if (started_count > 0) {
|
|
261
|
-
if (!ready_raised) {
|
|
262
|
-
console.log('Server ready');
|
|
263
|
-
this.raise('ready');
|
|
264
|
-
ready_raised = true;
|
|
265
|
-
}
|
|
266
|
-
if (callback) callback(null, true);
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
const final_error = err || last_error || new Error('No servers started.');
|
|
270
|
-
if (callback) callback(final_error);
|
|
271
|
-
};
|
|
272
|
-
const respond_not_found = (res) => {
|
|
273
|
-
if (!res.headersSent) {
|
|
274
|
-
const body = 'Not Found';
|
|
262
|
+
arr_ipv4_addresses = [...new Set(arr_ipv4_addresses)];
|
|
263
|
+
console.log('IPv4 addresses to bind:', arr_ipv4_addresses);
|
|
264
|
+
let num_to_start = arr_ipv4_addresses.length;
|
|
265
|
+
let started_count = 0;
|
|
266
|
+
let last_error = null;
|
|
267
|
+
let ready_raised = false;
|
|
268
|
+
if (num_to_start === 0) {
|
|
269
|
+
callback('No allowed network interfaces found.');
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const finalize_start = (err) => {
|
|
273
|
+
if (num_to_start !== 0) return;
|
|
274
|
+
if (started_count > 0) {
|
|
275
|
+
if (!ready_raised) {
|
|
276
|
+
console.log('Server ready');
|
|
277
|
+
this.raise('ready');
|
|
278
|
+
ready_raised = true;
|
|
279
|
+
}
|
|
280
|
+
if (callback) callback(null, true);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const final_error = err || last_error || new Error('No servers started.');
|
|
284
|
+
if (callback) callback(final_error);
|
|
285
|
+
};
|
|
286
|
+
const respond_not_found = (res) => {
|
|
287
|
+
if (!res.headersSent) {
|
|
288
|
+
const body = 'Not Found';
|
|
275
289
|
res.statusCode = 404;
|
|
276
290
|
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
|
|
277
291
|
res.setHeader('Content-Length', Buffer.byteLength(body));
|
|
@@ -326,70 +340,70 @@ class JSGUI_Single_Process_Server extends Evented_Class {
|
|
|
326
340
|
if (this.https_options) {
|
|
327
341
|
each(arr_ipv4_addresses, (ipv4_address) => {
|
|
328
342
|
try {
|
|
329
|
-
var https_server = https.createServer(this.https_options, function(req, res) {
|
|
343
|
+
var https_server = https.createServer(this.https_options, function (req, res) {
|
|
330
344
|
process_request(req, res);
|
|
331
345
|
});
|
|
332
346
|
this.http_servers.push(https_server);
|
|
333
|
-
https_server.on('error', (err) => {
|
|
334
|
-
last_error = err;
|
|
335
|
-
if (err.code === 'EACCES') {
|
|
336
|
-
console.error('Permission denied:', err.message);
|
|
337
|
-
} else if (err.code === 'EADDRINUSE') {
|
|
338
|
-
console.error(`Address ${ipv4_address}:${port} already in use; skipping.`);
|
|
339
|
-
} else {
|
|
340
|
-
console.error('https_server error:', err);
|
|
341
|
-
}
|
|
342
|
-
num_to_start--;
|
|
343
|
-
finalize_start(err);
|
|
344
|
-
});
|
|
345
|
-
https_server.timeout = 10800000;
|
|
346
|
-
https_server.listen(port, ipv4_address, () => {
|
|
347
|
-
console.log('* Server running at https://' + ipv4_address + ':' + port + '/');
|
|
348
|
-
started_count++;
|
|
349
|
-
num_to_start--;
|
|
350
|
-
finalize_start(null);
|
|
351
|
-
});
|
|
352
|
-
} catch (err) {
|
|
353
|
-
console.log('https_server err', err);
|
|
354
|
-
num_to_start--;
|
|
355
|
-
finalize_start(err);
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
} else {
|
|
359
|
-
|
|
360
|
-
try {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
this.http_servers.push(http_server);
|
|
365
|
-
http_server.on('error', (err) => {
|
|
366
|
-
last_error = err;
|
|
367
|
-
if (err.code === 'EACCES') {
|
|
368
|
-
console.error('Permission denied:', err.message);
|
|
369
|
-
} else if (err.code === 'EADDRINUSE') {
|
|
370
|
-
console.error(`Address ${ipv4_address}:${port} already in use; skipping.`);
|
|
371
|
-
} else {
|
|
372
|
-
console.error('http_server error:', err);
|
|
373
|
-
}
|
|
374
|
-
num_to_start--;
|
|
375
|
-
finalize_start(err);
|
|
376
|
-
});
|
|
377
|
-
http_server.timeout = 10800000;
|
|
378
|
-
http_server.listen(port, ipv4_address, () => {
|
|
379
|
-
console.log('* Server running at http://' + ipv4_address + ':' + port + '/');
|
|
380
|
-
started_count++;
|
|
381
|
-
num_to_start--;
|
|
382
|
-
finalize_start(null);
|
|
383
|
-
});
|
|
384
|
-
} catch (err) {
|
|
385
|
-
console.log('http_server err', err);
|
|
386
|
-
num_to_start--;
|
|
387
|
-
finalize_start(err);
|
|
388
|
-
}
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
});
|
|
347
|
+
https_server.on('error', (err) => {
|
|
348
|
+
last_error = err;
|
|
349
|
+
if (err.code === 'EACCES') {
|
|
350
|
+
console.error('Permission denied:', err.message);
|
|
351
|
+
} else if (err.code === 'EADDRINUSE') {
|
|
352
|
+
console.error(`Address ${ipv4_address}:${port} already in use; skipping.`);
|
|
353
|
+
} else {
|
|
354
|
+
console.error('https_server error:', err);
|
|
355
|
+
}
|
|
356
|
+
num_to_start--;
|
|
357
|
+
finalize_start(err);
|
|
358
|
+
});
|
|
359
|
+
https_server.timeout = 10800000;
|
|
360
|
+
https_server.listen(port, ipv4_address, () => {
|
|
361
|
+
console.log('* Server running at https://' + ipv4_address + ':' + port + '/');
|
|
362
|
+
started_count++;
|
|
363
|
+
num_to_start--;
|
|
364
|
+
finalize_start(null);
|
|
365
|
+
});
|
|
366
|
+
} catch (err) {
|
|
367
|
+
console.log('https_server err', err);
|
|
368
|
+
num_to_start--;
|
|
369
|
+
finalize_start(err);
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
} else {
|
|
373
|
+
each(arr_ipv4_addresses, (ipv4_address) => {
|
|
374
|
+
try {
|
|
375
|
+
var http_server = http.createServer(function (req, res) {
|
|
376
|
+
process_request(req, res);
|
|
377
|
+
});
|
|
378
|
+
this.http_servers.push(http_server);
|
|
379
|
+
http_server.on('error', (err) => {
|
|
380
|
+
last_error = err;
|
|
381
|
+
if (err.code === 'EACCES') {
|
|
382
|
+
console.error('Permission denied:', err.message);
|
|
383
|
+
} else if (err.code === 'EADDRINUSE') {
|
|
384
|
+
console.error(`Address ${ipv4_address}:${port} already in use; skipping.`);
|
|
385
|
+
} else {
|
|
386
|
+
console.error('http_server error:', err);
|
|
387
|
+
}
|
|
388
|
+
num_to_start--;
|
|
389
|
+
finalize_start(err);
|
|
390
|
+
});
|
|
391
|
+
http_server.timeout = 10800000;
|
|
392
|
+
http_server.listen(port, ipv4_address, () => {
|
|
393
|
+
console.log('* Server running at http://' + ipv4_address + ':' + port + '/');
|
|
394
|
+
started_count++;
|
|
395
|
+
num_to_start--;
|
|
396
|
+
finalize_start(null);
|
|
397
|
+
});
|
|
398
|
+
} catch (err) {
|
|
399
|
+
console.log('http_server err', err);
|
|
400
|
+
num_to_start--;
|
|
401
|
+
finalize_start(err);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
});
|
|
393
407
|
}
|
|
394
408
|
});
|
|
395
409
|
}
|
|
@@ -441,64 +455,64 @@ if (require.main === module) {
|
|
|
441
455
|
}
|
|
442
456
|
current();
|
|
443
457
|
|
|
444
|
-
} else {}
|
|
458
|
+
} else { }
|
|
445
459
|
|
|
446
460
|
//
|
|
447
461
|
|
|
448
462
|
const summary = {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
463
|
+
"classes": [
|
|
464
|
+
"JSGUI_Single_Process_Server",
|
|
465
|
+
"Server_Resource_Pool",
|
|
466
|
+
"Router",
|
|
467
|
+
"Website_Resource",
|
|
468
|
+
"Server_Page_Context",
|
|
469
|
+
"Web_Admin_Page_Control",
|
|
470
|
+
"Web_Admin_Panel_Control",
|
|
471
|
+
"Website",
|
|
472
|
+
"HTTP_Website_Publisher",
|
|
473
|
+
"Webpage"
|
|
474
|
+
],
|
|
475
|
+
"methods": {
|
|
476
|
+
"JSGUI_Single_Process_Server": [
|
|
477
|
+
"constructor",
|
|
478
|
+
"start",
|
|
479
|
+
"stop"
|
|
480
|
+
],
|
|
481
|
+
"Server_Resource_Pool": [
|
|
482
|
+
"constructor"
|
|
483
|
+
],
|
|
484
|
+
"Router": [
|
|
485
|
+
"constructor",
|
|
486
|
+
"set_route",
|
|
487
|
+
"unset_route"
|
|
488
|
+
],
|
|
489
|
+
"Website_Resource": [
|
|
490
|
+
"constructor",
|
|
491
|
+
"process"
|
|
492
|
+
],
|
|
493
|
+
"Server_Page_Context": [
|
|
494
|
+
"constructor",
|
|
495
|
+
"respond_string"
|
|
496
|
+
],
|
|
497
|
+
"Web_Admin_Page_Control": [
|
|
498
|
+
"constructor"
|
|
499
|
+
],
|
|
500
|
+
"Web_Admin_Panel_Control": [
|
|
501
|
+
"constructor"
|
|
502
|
+
],
|
|
503
|
+
"Website": [
|
|
504
|
+
"constructor",
|
|
505
|
+
"add_page",
|
|
506
|
+
"add_page_resource",
|
|
507
|
+
"add_page_resource_from_webpage"
|
|
508
|
+
],
|
|
509
|
+
"HTTP_Website_Publisher": [
|
|
510
|
+
"constructor"
|
|
511
|
+
],
|
|
512
|
+
"Webpage": [
|
|
513
|
+
"constructor"
|
|
514
|
+
]
|
|
515
|
+
}
|
|
502
516
|
}
|
|
503
517
|
|
|
504
518
|
JSGUI_Single_Process_Server.summary = summary;
|