@daisy/ace-axe-runner-electron 1.2.4 → 1.2.6-alpha.4

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/src/init.js CHANGED
@@ -1,8 +1,31 @@
1
1
  'use strict';
2
2
 
3
+ // TOO LATE FOR JEST RUNNER DUE TO AFTER ELECTRON APP.READY!
4
+ // (see package.json patcher script "patchElectronJestRunner3")
5
+ // // NO_HTTP_ADD
6
+ // const electron = require('electron');
7
+ // const protocol = electron.protocol;
8
+ // const ACE_ELECTRON_HTTP_PROTOCOL = "acehttps";
9
+ // // app.commandLine.appendSwitch("autoplay-policy", "no-user-gesture-required");
10
+ // protocol.registerSchemesAsPrivileged([{
11
+ // privileges: {
12
+ // allowServiceWorkers: false,
13
+ // bypassCSP: false,
14
+ // corsEnabled: true,
15
+ // secure: true,
16
+ // standard: true,
17
+ // stream: true,
18
+ // supportFetchAPI: true,
19
+ // },
20
+ // scheme: ACE_ELECTRON_HTTP_PROTOCOL,
21
+ // }]);
22
+
23
+ const mime = require('mime-types');
24
+
25
+ const nodeStream = require('stream');
26
+
3
27
  const path = require('path');
4
28
  const fs = require('fs');
5
- const url = require('url');
6
29
 
7
30
  const electron = require('electron');
8
31
  const app = electron.app;
@@ -13,13 +36,6 @@ const BrowserWindow = electron.BrowserWindow;
13
36
 
14
37
  const fsOriginal = require('original-fs');
15
38
 
16
- const express = require('express');
17
- const portfinder = require('portfinder');
18
- // const http = require('http');
19
- const https = require('https');
20
-
21
- const generateSelfSignedData = require('./selfsigned').generateSelfSignedData;
22
-
23
39
  const isDev = process && process.env && (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === 'true');
24
40
  const showWindow = false;
25
41
 
@@ -32,16 +48,28 @@ const SESSION_PARTITION = "persist:axe";
32
48
 
33
49
  const HTTP_QUERY_PARAM = "AXE_RUNNER";
34
50
 
35
- let expressApp;
36
- let httpServer;
37
- let port;
38
- let ip;
39
- let proto;
40
- let rootUrl;
41
-
51
+ const ACE_ELECTRON_HTTP_PROTOCOL = "acehttps";
52
+
53
+ // NO_HTTP_REMOVE
54
+ // const express = require('express');
55
+ // const portfinder = require('portfinder');
56
+ // // const http = require('http');
57
+ // const https = require('https');
58
+ // const generateSelfSignedData = require('./selfsigned').generateSelfSignedData;
59
+ // let expressApp;
60
+ // let httpServer;
61
+ // let port;
62
+ // let ip;
63
+ // let proto;
64
+ // let rootUrl;
42
65
  let httpServerStartWasRequested = false;
43
66
  let httpServerStarted = false;
44
67
 
68
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner ELECTRON MODULE INSTANCE`);
69
+
70
+ // NO_HTTP_ADD
71
+ const rootUrl = `${ACE_ELECTRON_HTTP_PROTOCOL}://0.0.0.0`;
72
+
45
73
  let browserWindows = undefined;
46
74
 
47
75
  const jsCache = {};
@@ -50,6 +78,126 @@ let _firstTimeInit = true;
50
78
 
51
79
  let iHttpReq = 0;
52
80
 
81
+ // NO_HTTP_ADD
82
+ class BufferReadableStream extends nodeStream.Readable {
83
+ constructor(buffer) {
84
+ super();
85
+ this.buffer = buffer;
86
+ this.alreadyRead = 0;
87
+ }
88
+ _read(size) {
89
+ if (this.alreadyRead >= this.buffer.length) {
90
+ this.push(null);
91
+ return;
92
+ }
93
+
94
+ let chunk = this.alreadyRead ?
95
+ this.buffer.slice(this.alreadyRead) :
96
+ this.buffer;
97
+
98
+ if (size) {
99
+ let l = size;
100
+ if (size > chunk.length) {
101
+ l = chunk.length;
102
+ }
103
+
104
+ chunk = chunk.slice(0, l);
105
+ }
106
+
107
+ this.alreadyRead += chunk.length;
108
+ this.push(chunk);
109
+ }
110
+ }
111
+ function bufferToStream(buffer) {
112
+ return new BufferReadableStream(buffer);
113
+ }
114
+
115
+ let _streamProtocolHandler = undefined;
116
+ const streamProtocolHandler = async (
117
+ req,
118
+ callback) => {
119
+
120
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} streamProtocolHandler req.url: ${req.url}`);
121
+ const u = new URL(req.url);
122
+
123
+ if (LOG_DEBUG) {
124
+ Object.keys(req.headers).forEach((header) => {
125
+ const val = req.headers[header];
126
+
127
+ console.log(`${ACE_LOG_PREFIX} streamProtocolHandler req.header: ${header} => ${val}`);
128
+
129
+ // if (val) {
130
+ // headers[header] = val;
131
+ // }
132
+ });
133
+ }
134
+
135
+ let ref = u.origin;
136
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} streamProtocolHandler u.origin: ${ref}`);
137
+ if (req.referrer && req.referrer.trim()) {
138
+ ref = req.referrer;
139
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} streamProtocolHandler req.referrer: ${ref}`);
140
+ }
141
+
142
+ const headers = {};
143
+
144
+ if (ref && ref !== "null" && !/^https?:\/\/localhost.+/.test(ref) && !/^https?:\/\/127\.0\.0\.1.+/.test(ref)) {
145
+ headers.referer = ref;
146
+ } else {
147
+ headers.referer = `${ACE_ELECTRON_HTTP_PROTOCOL}://0.0.0.0/`;
148
+ }
149
+
150
+ // CORS everything!
151
+ headers["Access-Control-Allow-Origin"] = "*";
152
+ headers["Access-Control-Allow-Methods"] = "GET, HEAD, OPTIONS"; // POST, DELETE, PUT, PATCH
153
+ // tslint:disable-next-line:max-line-length
154
+ headers["Access-Control-Allow-Headers"] = "Content-Type, Content-Length, Accept-Ranges, Content-Range, Range, Link, Transfer-Encoding, X-Requested-With, Authorization, Accept, Origin, User-Agent, DNT, Cache-Control, Keep-Alive, If-Modified-Since";
155
+ // tslint:disable-next-line:max-line-length
156
+ headers["Access-Control-Expose-Headers"] = "Content-Type, Content-Length, Accept-Ranges, Content-Range, Range, Link, Transfer-Encoding, X-Requested-With, Authorization, Accept, Origin, User-Agent, DNT, Cache-Control, Keep-Alive, If-Modified-Since";
157
+
158
+ if (!_streamProtocolHandler) {
159
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} !? _streamProtocolHandler`);
160
+
161
+ const buff = Buffer.from("<html><body><p>Internal Server Error</p><p>!_streamProtocolHandler</p></body></html>");
162
+ headers["Content-Length"] = buff.length.toString();
163
+ callback({
164
+ data: bufferToStream(buff),
165
+ headers,
166
+ statusCode: 500,
167
+ });
168
+ return;
169
+ }
170
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} BEFORE _streamProtocolHandler ${req.url}`);
171
+ await _streamProtocolHandler(req, callback, headers);
172
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} AFTER _streamProtocolHandler ${req.url}`);
173
+ };
174
+ app.whenReady().then(async () => {
175
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} Electron app ready`);
176
+
177
+ // try {
178
+ // await clearSessions();
179
+ // } catch (err) {
180
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} clearSessions fail?`);
181
+ // }
182
+
183
+ // if (session.defaultSession) {
184
+ // session.defaultSession.protocol.registerStreamProtocol(
185
+ // ACE_ELECTRON_HTTP_PROTOCOL,
186
+ // streamProtocolHandler);
187
+ // }
188
+ const sess = session.fromPartition(SESSION_PARTITION, { cache: true });
189
+ if (sess) {
190
+ sess.protocol.registerStreamProtocol(
191
+ ACE_ELECTRON_HTTP_PROTOCOL,
192
+ streamProtocolHandler);
193
+
194
+ sess.setPermissionRequestHandler((wc, permission, callback) => {
195
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} setPermissionRequestHandler ${wc.getURL()} => ${permission}`);
196
+ callback(true);
197
+ });
198
+ }
199
+ });
200
+
53
201
  function loadUrl(browserWindow) {
54
202
  browserWindow.ace__loadUrlPending = undefined;
55
203
 
@@ -151,6 +299,8 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
151
299
  }
152
300
  axeRunnerInit.todo = false;
153
301
 
302
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunnerInit TODO ...`);
303
+
154
304
  const firstTimeInit = _firstTimeInit;
155
305
  _firstTimeInit = false;
156
306
 
@@ -172,7 +322,8 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
172
322
  webviewTag: false,
173
323
  enableRemoteModule: false,
174
324
  partition: SESSION_PARTITION,
175
- nativeWindowOpen: false, // The default of nativeWindowOpen is deprecated and will be changing from false to true in Electron 15. See https://github.com/electron/electron/issues/28511
325
+ // (electron) Deprecation Warning: Disabling nativeWindowOpen is deprecated. The nativeWindowOpen option will be removed in Electron 18.
326
+ // nativeWindowOpen: false, // The default of nativeWindowOpen is deprecated and will be changing from false to true in Electron 15. See https://github.com/electron/electron/issues/28511
176
327
  },
177
328
  });
178
329
 
@@ -183,8 +334,17 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
183
334
  urls: [],
184
335
  }, (details, callback) => {
185
336
  if (details.url
186
- && /^https?:\/\//.test(details.url)
187
- && ((rootUrl && !details.url.startsWith(rootUrl)) || (!rootUrl && !/^https?:\/\/127.0.0.1/.test(details.url)))
337
+ &&
338
+ (
339
+ /^file:\/\//.test(details.url)
340
+ ||
341
+ /^https?:\/\//.test(details.url)
342
+ // && (
343
+ // (rootUrl && !details.url.startsWith(rootUrl))
344
+ // ||
345
+ // (!rootUrl && !/^https?:\/\/127.0.0.1/.test(details.url))
346
+ // )
347
+ )
188
348
  ) {
189
349
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} onBeforeRequest BLOCK: ${details.url} (${rootUrl})`);
190
350
 
@@ -227,15 +387,18 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
227
387
  return;
228
388
  }
229
389
 
230
- app.on("certificate-error", (event, webContents, u, error, certificate, callback) => {
231
- if (u.indexOf(`${rootUrl}/`) === 0) {
232
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert error OKAY ${u}`);
233
- callback(true);
234
- return;
235
- }
236
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert error FAIL ${u}`);
237
- callback(false);
238
- });
390
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunnerInit firstTimeInit ...`);
391
+
392
+ // NO_HTTP_REMOVE
393
+ // app.on("certificate-error", (event, webContents, u, error, certificate, callback) => {
394
+ // if (u.indexOf(`${rootUrl}/`) === 0) {
395
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert error OKAY ${u}`);
396
+ // callback(true);
397
+ // return;
398
+ // }
399
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert error FAIL ${u}`);
400
+ // callback(false);
401
+ // });
239
402
 
240
403
  // const filter = { urls: ["*", "*://*/*"] };
241
404
 
@@ -260,25 +423,23 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
260
423
  // }
261
424
  // };
262
425
 
263
- const setCertificateVerifyProcCB = (request, callback) => {
264
-
265
- if (request.hostname === ip) {
266
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert verify OKAY ${request.hostname}`);
267
- callback(0); // OK
268
- return;
269
- }
270
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert verify FALLBACK ${request.hostname}`);
271
- callback(-3); // Chromium
272
- // callback(-2); // Fail
273
- };
274
-
275
- const sess = session.fromPartition(SESSION_PARTITION, { cache: true }); // || session.defaultSession;
276
-
277
- if (sess) {
278
- // sess.webRequest.onHeadersReceived(filter, onHeadersReceivedCB);
279
- // sess.webRequest.onBeforeSendHeaders(filter, onBeforeSendHeadersCB);
280
- sess.setCertificateVerifyProc(setCertificateVerifyProcCB);
281
- }
426
+ // NO_HTTP_REMOVE
427
+ // const setCertificateVerifyProcCB = (request, callback) => {
428
+ // if (request.hostname === ip) {
429
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert verify OKAY ${request.hostname}`);
430
+ // callback(0); // OK
431
+ // return;
432
+ // }
433
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTPS cert verify FALLBACK ${request.hostname}`);
434
+ // callback(-3); // Chromium
435
+ // // callback(-2); // Fail
436
+ // };
437
+ // const sess = session.fromPartition(SESSION_PARTITION, { cache: true }); // || session.defaultSession;
438
+ // if (sess) {
439
+ // // sess.webRequest.onHeadersReceived(filter, onHeadersReceivedCB);
440
+ // // sess.webRequest.onBeforeSendHeaders(filter, onBeforeSendHeadersCB);
441
+ // sess.setCertificateVerifyProc(setCertificateVerifyProcCB);
442
+ // }
282
443
 
283
444
  // ipcMain
284
445
  eventEmmitter.on('AXE_RUNNER_CLOSE', (event, arg) => {
@@ -303,13 +464,17 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
303
464
  }
304
465
  browserWindows = undefined;
305
466
 
467
+ // NO_HTTP_ADD
468
+ _streamProtocolHandler = undefined;
469
+
306
470
  httpServerStarted = false;
307
471
  httpServerStartWasRequested = false;
308
472
 
309
- if (httpServer) {
310
- httpServer.close();
311
- httpServer = undefined;
312
- }
473
+ // NO_HTTP_REMOVE
474
+ // if (httpServer) {
475
+ // httpServer.close();
476
+ // httpServer = undefined;
477
+ // }
313
478
 
314
479
  let _timeOutID = setTimeout(() => {
315
480
  _timeOutID = undefined;
@@ -341,6 +506,7 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
341
506
  }
342
507
  }
343
508
 
509
+ // clearSessions()
344
510
  const sess = session.fromPartition(SESSION_PARTITION, { cache: true }); // || session.defaultSession;
345
511
  if (sess) {
346
512
  setTimeout(async () => {
@@ -396,7 +562,8 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
396
562
  console.log(uarel);
397
563
  }
398
564
  // windows! file://C:\aa\bb\chapter.xhtml
399
- const uarelObj = url.parse(uarel.replace(/\\/g, "/"));
565
+
566
+ const uarelObj = new URL(uarel.replace(/\\/g, "/"));
400
567
  const windowsDrive = uarelObj.hostname ? `${uarelObj.hostname.toUpperCase()}:` : "";
401
568
  if (LOG_DEBUG_URLS) {
402
569
  console.log("######## URL 2");
@@ -444,8 +611,6 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
444
611
  return;
445
612
  }
446
613
 
447
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner free browser window in pool: ${browserWindow.ace__poolIndex}`);
448
-
449
614
  browserWindow.ace__eventEmmitterSender = sender;
450
615
  browserWindow.ace__replySent = false;
451
616
  browserWindow.ace__timeout = undefined;
@@ -453,13 +618,15 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
453
618
  browserWindow.ace__currentUrlOriginal = uarel;
454
619
  browserWindow.ace__currentUrl = httpUrl;
455
620
 
621
+ if (LOG_DEBUG) console.log(`\n\n${ACE_LOG_PREFIX} axeRunner free browser window in pool: ${browserWindow.ace__poolIndex} ${browserWindow.ace__previousUrl} ${browserWindow.ace__currentUrlOriginal} ${browserWindow.ace__currentUrl}\n\n`);
622
+
456
623
  browserWindow.webContents.once("did-start-loading", () => {
457
624
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner did-start-loading ${browserWindow.ace__poolIndex} ${browserWindow.ace__currentUrlOriginal} --- ${browserWindow.ace__currentUrl}`);
458
625
  });
459
626
  // browserWindow.webContents.once("did-stop-loading", () => {
460
627
  // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner did-stop-loading ${browserWindow.ace__poolIndex} ${browserWindow.ace__currentUrlOriginal} --- ${browserWindow.ace__currentUrl}`);
461
628
  // });
462
- browserWindow.webContents.once("did-fail-load", (event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId) => {
629
+ const didFailLoadHandler = (event, errorCode, errorDescription, validatedURL, isMainFrame, frameProcessId, frameRoutingId) => {
463
630
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner did-fail-load ${browserWindow.ace__poolIndex} ${browserWindow.ace__currentUrlOriginal} --- ${browserWindow.ace__currentUrl}`, "\n", `${errorCode} - ${errorDescription} - ${validatedURL} - ${isMainFrame} - ${frameProcessId} - ${frameRoutingId}`);
464
631
 
465
632
  // https://cs.chromium.org/chromium/src/net/base/net_error_list.h
@@ -483,11 +650,16 @@ function axeRunnerInit(eventEmmitter, CONCURRENT_INSTANCES) {
483
650
  err: `did-fail-load: ${errorCode} - ${errorDescription} - ${validatedURL} - ${isMainFrame} - ${frameProcessId} - ${frameRoutingId}`,
484
651
  url: browserWindow.ace__currentUrlOriginal
485
652
  });
486
- });
653
+ };
654
+ browserWindow.webContents.once("did-fail-load", didFailLoadHandler);
487
655
  // browserWindow.webContents.once("dom-ready", () => { // occurs early
488
656
  // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner dom-ready ${browserWindow.ace__poolIndex} ${browserWindow.ace__currentUrlOriginal} --- ${browserWindow.ace__currentUrl}`);
489
657
  // });
490
658
  browserWindow.webContents.once("did-finish-load", () => {
659
+ // browserWindow.webContents.setMaxListeners(11+) ?
660
+ // (node:5505) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 did-fail-load listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
661
+ browserWindow.webContents.removeListener("did-fail-load", didFailLoadHandler);
662
+
491
663
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner did-finish-load ${browserWindow.ace__poolIndex} ${browserWindow.ace__currentUrlOriginal} --- ${browserWindow.ace__currentUrl}`);
492
664
 
493
665
  browserWindow.ace__TIME_executeJavaScript = process.hrtime();
@@ -578,7 +750,7 @@ new Promise((resolve, reject) => {
578
750
  } else {
579
751
  browserWindow.ace__loadUrlPending = httpUrl;
580
752
  }
581
- }
753
+ } // poolPush()
582
754
 
583
755
  if (!httpServerStartWasRequested) { // lazy init
584
756
  httpServerStartWasRequested = true;
@@ -587,19 +759,30 @@ new Promise((resolve, reject) => {
587
759
 
588
760
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner starting server ...`);
589
761
 
590
- startAxeServer(basedir, scripts, scriptContents).then(() => {
591
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner server started`);
592
- httpServerStarted = true;
593
-
594
- poolCheck();
595
- }).catch((err) => {
762
+ // NO_HTTP_ADD
763
+ try {
764
+ startAxeServer(basedir, scripts, scriptContents);
765
+ } catch (err) {
596
766
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner server error`);
597
767
  console.log(err);
598
768
  browserWindow.ace__eventEmmitterSender.send("AXE_RUNNER_RUN_", {
599
769
  err,
600
770
  url: browserWindow.ace__currentUrlOriginal
601
771
  });
602
- });
772
+ return;
773
+ }
774
+
775
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner server started`);
776
+ httpServerStarted = true;
777
+ poolCheck();
778
+
779
+ // NO_HTTP_REMOVE
780
+ // startAxeServer(basedir, scripts, scriptContents).then(() => {
781
+ // // ...
782
+ // httpServerStarted = true;
783
+ // }).catch((err) => {
784
+ // // ...
785
+ // });
603
786
  } else {
604
787
  poolPush();
605
788
  }
@@ -607,10 +790,11 @@ new Promise((resolve, reject) => {
607
790
  }
608
791
  axeRunnerInit.todo = true;
609
792
 
610
- const filePathsExpressStaticNotExist = {};
793
+ // const filePathsExpressStaticNotExist = {};
611
794
  function startAxeServer(basedir, scripts, scriptContents) {
612
795
 
613
- return new Promise((resolve, reject) => {
796
+ // NO_HTTP_REMOVE
797
+ // return new Promise((resolve, reject) => {
614
798
 
615
799
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner startAxeServer...`);
616
800
 
@@ -627,16 +811,12 @@ function startAxeServer(basedir, scripts, scriptContents) {
627
811
  scriptsMarkup += `<script data-ace="" src="/${HTTP_QUERY_PARAM}/${filename}"> </script>`;
628
812
  });
629
813
 
630
- expressApp = express();
631
- // expressApp.enable('strict routing');
632
-
633
- // expressApp.use("/", (req, res, next) => {
634
- // if (LOG_DEBUG) console.log("HTTP: " + req.url);
635
- // next();
636
- // });
637
-
638
- expressApp.basedir = basedir;
639
- expressApp.use("/", (req, res, next) => {
814
+ // NO_HTTP_ADD
815
+ _streamProtocolHandler = async (
816
+ req,
817
+ callback,
818
+ headers) => {
819
+ const u = new URL(req.url);
640
820
 
641
821
  for (const scriptPath of scripts) {
642
822
  const filename = path.basename(scriptPath);
@@ -648,22 +828,29 @@ function startAxeServer(basedir, scripts, scriptContents) {
648
828
  // if (LOG_DEBUG) console.log(js);
649
829
  jsCache[scriptPath] = js;
650
830
  } else {
651
- // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTP already loaded ${scriptPath}`);
831
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTP already loaded ${scriptPath}`);
652
832
  }
653
- res.setHeader("Content-Type", "text/javascript");
654
- res.send(js);
833
+ const buff = Buffer.from(js);
834
+ headers["Content-Length"] = buff.length.toString();
835
+ headers["Content-Type"] = "text/javascript";
836
+ callback({
837
+ data: bufferToStream(buff),
838
+ headers,
839
+ statusCode: 200,
840
+ });
655
841
  return;
656
842
  }
657
843
  }
658
844
 
659
- if (req.query[HTTP_QUERY_PARAM]) {
845
+ const queryParam = u.searchParams.get(HTTP_QUERY_PARAM) || undefined;
846
+ if (queryParam) {
660
847
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTP intercept ${req.url}`);
661
848
 
662
849
  if (LOG_DEBUG_URLS) {
663
850
  console.log(">>>>>>>>>> URL 1");
664
851
  console.log(req.url);
665
852
  }
666
- const ptn = url.parse(req.url).pathname;
853
+ const ptn = u.pathname;
667
854
  if (LOG_DEBUG_URLS) {
668
855
  console.log(">>>>>>>>>> URL 2");
669
856
  console.log(ptn);
@@ -673,18 +860,35 @@ function startAxeServer(basedir, scripts, scriptContents) {
673
860
  console.log(">>>>>>>>>> URL 3");
674
861
  console.log(pn);
675
862
  }
676
- let fileSystemPath = path.join(expressApp.basedir, pn);
863
+
864
+ let fileSystemPath = path.join(basedir, pn);
677
865
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} filepath to read: ${fileSystemPath}`);
678
866
  if (!fs.existsSync(fileSystemPath)) {
679
867
  fileSystemPath = pn;
680
868
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} filepath to read (corrected): ${fileSystemPath}`);
869
+ if (!fs.existsSync(fileSystemPath)) {
870
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} FILE DOES NOT EXIST!! ${fileSystemPath}`);
871
+
872
+ const buff = Buffer.from(`<html><body><p>Internal Server Error</p><p>404?! ${fileSystemPath}</p></body></html>`);
873
+ headers["Content-Length"] = buff.length.toString();
874
+ callback({
875
+ data: bufferToStream(buff),
876
+ headers,
877
+ statusCode: 404,
878
+ });
879
+ return;
880
+ }
681
881
  }
682
882
 
683
883
  // let html = fs.readFileSync(fileSystemPath, { encoding: "utf8" });
684
884
  fs.readFile(fileSystemPath, { encoding: "utf8" }, (err, html) => {
685
885
  if (err) {
686
886
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTML file load??! ${req.url}`);
687
- res.status(404).end();
887
+ callback({
888
+ data: null,
889
+ headers,
890
+ statusCode: 404,
891
+ });
688
892
  return;
689
893
  }
690
894
 
@@ -699,139 +903,252 @@ function startAxeServer(basedir, scripts, scriptContents) {
699
903
  if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTML neither </head> nor </body>?! ${req.url}`);
700
904
  }
701
905
 
702
- res.setHeader("Content-Type", "application/xhtml+xml");
703
- res.send(html);
906
+ const buff = Buffer.from(html);
907
+ headers["Content-Length"] = buff.length.toString();
908
+ headers["Content-Type"] = "application/xhtml+xml";
909
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} CALLBACK HEADERS ${req.url} ${JSON.stringify(headers)}`);
910
+ callback({
911
+ data: bufferToStream(buff),
912
+ headers,
913
+ statusCode: 200,
914
+ });
915
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} POST-CALLBACK ${req.url}`);
704
916
  });
705
917
  return;
706
918
  }
707
919
 
708
- next();
709
- });
710
-
711
- if (isDev) { // handle WebInspector JS maps etc.
712
- expressApp.use("/", (req, res, next) => {
713
- // const url = new URL(`https://fake.org${req.url}`);
714
- // const pathname = url.pathname;
715
- const pathname = decodeURI(url.parse(req.url).pathname);
716
-
717
- const filePath = path.join(basedir, pathname);
718
- if (filePathsExpressStaticNotExist[filePath]) {
719
- res.status(404).send(filePathsExpressStaticNotExist[filePath]);
920
+ // equivalent to Express static:
921
+
922
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} Express static emulate: ${req.url}`);
923
+
924
+ if (LOG_DEBUG_URLS) {
925
+ console.log(">>>>>>>>>>- URL 1");
926
+ console.log(req.url);
927
+ }
928
+ const ptn = u.pathname;
929
+ if (LOG_DEBUG_URLS) {
930
+ console.log(">>>>>>>>>>- URL 2");
931
+ console.log(ptn);
932
+ }
933
+ const pn = decodeURI(ptn);
934
+ if (LOG_DEBUG_URLS) {
935
+ console.log(">>>>>>>>>>- URL 3");
936
+ console.log(pn);
937
+ }
938
+ let fileSystemPath = path.join(basedir, pn);
939
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --filepath to read: ${fileSystemPath}`);
940
+ if (!fs.existsSync(fileSystemPath)) {
941
+ fileSystemPath = pn;
942
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --filepath to read (corrected): ${fileSystemPath}`);
943
+ if (!fs.existsSync(fileSystemPath)) {
944
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --FILE DOES NOT EXIST!! ${fileSystemPath}`);
945
+
946
+ const buff = Buffer.from(`<html><body><p>Internal Server Error</p><p>404?! ${fileSystemPath}</p></body></html>`);
947
+ headers["Content-Length"] = buff.length.toString();
948
+ callback({
949
+ data: bufferToStream(buff),
950
+ headers,
951
+ statusCode: 404,
952
+ });
720
953
  return;
721
954
  }
722
- fsOriginal.exists(filePath, (exists) => {
723
- if (exists) {
724
- fsOriginal.readFile(filePath, undefined, (err, data) => {
725
- if (err) {
726
- if (LOG_DEBUG) {
727
- console.log(`${ACE_LOG_PREFIX} HTTP FAIL fsOriginal.exists && ERR ${basedir} + ${req.url} => ${filePath}`, err);
728
- }
729
- filePathsExpressStaticNotExist[filePath] = err.toString();
730
- res.status(404).send(filePathsExpressStaticNotExist[filePath]);
731
- } else {
732
- // if (LOG_DEBUG) {
733
- // console.log(`${ACE_LOG_PREFIX} HTTP OK fsOriginal.exists ${basedir} + ${req.url} => ${filePath}`);
734
- // }
735
- next();
736
- // res.send(data);
737
- }
738
- });
739
- } else {
740
- fs.exists(filePath, (exists) => {
741
- if (exists) {
742
- fs.readFile(filePath, undefined, (err, data) => {
743
- if (err) {
744
- if (LOG_DEBUG) {
745
- console.log(`${ACE_LOG_PREFIX} HTTP FAIL !fsOriginal.exists && fs.exists && ERR ${basedir} + ${req.url} => ${filePath}`, err);
746
- }
747
- filePathsExpressStaticNotExist[filePath] = err.toString();
748
- res.status(404).send(filePathsExpressStaticNotExist[filePath]);
749
- } else {
750
- if (LOG_DEBUG) {
751
- console.log(`${ACE_LOG_PREFIX} HTTP OK !fsOriginal.exists && fs.exists ${basedir} + ${req.url} => ${filePath}`);
752
- }
753
- next();
754
- // res.send(data);
755
- }
756
- });
757
- } else {
758
- if (LOG_DEBUG) {
759
- console.log(`${ACE_LOG_PREFIX} HTTP FAIL !fsOriginal.exists && !fs.exists ${basedir} + ${req.url} => ${filePath}`);
760
- }
761
- res.status(404).end();
762
- }
763
- });
764
- }
955
+ }
956
+ try {
957
+ let mediaType = mime.lookup(fileSystemPath) || "stream/octet";
958
+ const stats = fs.statSync(fileSystemPath);
959
+ headers["Content-Length"] = stats.size;
960
+ headers["Content-Type"] = mediaType;
961
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --CALLBACK HEADERS ${req.url} ${JSON.stringify(headers)}`);
962
+ const steam = fs.createReadStream(fileSystemPath);
963
+ callback({
964
+ data: steam,
965
+ headers,
966
+ statusCode: 200,
765
967
  });
766
- });
767
- }
968
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --POST-CALLBACK ${req.url}`);
969
+ } catch (fsErr) {
970
+ if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} --fsErr ${fsErr}`);
768
971
 
769
- // https://expressjs.com/en/4x/api.html#express.static
770
- const staticOptions = {
771
- dotfiles: "ignore",
772
- etag: true,
773
- // fallthrough: false,
774
- immutable: true,
775
- // index: "index.html",
776
- maxAge: "1d",
777
- redirect: false,
778
- // extensions: ["css", "otf"],
779
- // setHeaders: (res, _path, _stat) => {
780
- // // res.set('x-timestamp', Date.now())
781
- // setResponseCORS(res);
782
- // },
783
- };
784
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTP static path ${basedir}`);
785
- expressApp.use("/", express.static(basedir, staticOptions));
786
-
787
- const startHttp = function () {
788
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner generateSelfSignedData...`);
789
- generateSelfSignedData().then((certData) => {
790
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner generateSelfSignedData OK.`);
972
+ const buff = Buffer.from(`<html><body><p>Internal Server Error</p><p>fsErr: ${fsErr}</p></body></html>`);
973
+ headers["Content-Length"] = buff.length.toString();
974
+ callback({
975
+ data: bufferToStream(buff),
976
+ headers,
977
+ statusCode: 500,
978
+ });
979
+ }
791
980
 
792
- httpServer = https.createServer({ key: certData.private, cert: certData.cert }, expressApp).listen(port, () => {
793
- const p = httpServer.address().port;
981
+ // if (isDev) { // handle WebInspector JS maps etc.
982
+
983
+ // // const url = new URL(`https://fake.org${req.url}`);
984
+ // // const pathname = url.pathname;
985
+ // const pathname = decodeURI(u.pathname);
986
+
987
+ // const filePath = path.join(basedir, pathname);
988
+ // if (filePathsExpressStaticNotExist[filePath]) {
989
+
990
+ // const buff = Buffer.from(filePathsExpressStaticNotExist[filePath]);
991
+ // headers["Content-Length"] = buff.length.toString();
992
+ // headers["Content-Type"] = "plain/text";
993
+ // callback({
994
+ // data: bufferToStream(buff),
995
+ // headers,
996
+ // statusCode: 404,
997
+ // });
998
+ // return;
999
+ // }
1000
+ // fsOriginal.exists(filePath, (exists) => {
1001
+ // if (exists) {
1002
+ // fsOriginal.readFile(filePath, undefined, (err, data) => {
1003
+ // if (err) {
1004
+ // if (LOG_DEBUG) {
1005
+ // console.log(`${ACE_LOG_PREFIX} HTTP FAIL fsOriginal.exists && ERR ${basedir} + ${req.url} => ${filePath}`, err);
1006
+ // }
1007
+ // filePathsExpressStaticNotExist[filePath] = err.toString();
1008
+ // const buff = Buffer.from(filePathsExpressStaticNotExist[filePath]);
1009
+ // headers["Content-Length"] = buff.length.toString();
1010
+ // headers["Content-Type"] = "plain/text";
1011
+ // callback({
1012
+ // data: bufferToStream(buff),
1013
+ // headers,
1014
+ // statusCode: 404,
1015
+ // });
1016
+ // } else {
1017
+ // // if (LOG_DEBUG) {
1018
+ // // console.log(`${ACE_LOG_PREFIX} HTTP OK fsOriginal.exists ${basedir} + ${req.url} => ${filePath}`);
1019
+ // // }
1020
+ // callback({
1021
+ // data: null,
1022
+ // headers,
1023
+ // statusCode: 500,
1024
+ // });
1025
+ // }
1026
+ // });
1027
+ // } else {
1028
+ // fs.exists(filePath, (exists) => {
1029
+ // if (exists) {
1030
+ // fs.readFile(filePath, undefined, (err, data) => {
1031
+ // if (err) {
1032
+ // if (LOG_DEBUG) {
1033
+ // console.log(`${ACE_LOG_PREFIX} HTTP FAIL !fsOriginal.exists && fs.exists && ERR ${basedir} + ${req.url} => ${filePath}`, err);
1034
+ // }
1035
+ // filePathsExpressStaticNotExist[filePath] = err.toString();
1036
+ // const buff = Buffer.from(filePathsExpressStaticNotExist[filePath]);
1037
+ // headers["Content-Length"] = buff.length.toString();
1038
+ // headers["Content-Type"] = "plain/text";
1039
+ // callback({
1040
+ // data: bufferToStream(buff),
1041
+ // headers,
1042
+ // statusCode: 404,
1043
+ // });
1044
+ // } else {
1045
+ // if (LOG_DEBUG) {
1046
+ // console.log(`${ACE_LOG_PREFIX} HTTP OK !fsOriginal.exists && fs.exists ${basedir} + ${req.url} => ${filePath}`);
1047
+ // }
1048
+ // callback({
1049
+ // data: null,
1050
+ // headers,
1051
+ // statusCode: 500,
1052
+ // });
1053
+ // }
1054
+ // });
1055
+ // } else {
1056
+ // if (LOG_DEBUG) {
1057
+ // console.log(`${ACE_LOG_PREFIX} HTTP FAIL !fsOriginal.exists && !fs.exists ${basedir} + ${req.url} => ${filePath}`);
1058
+ // }
1059
+ // callback({
1060
+ // data: null,
1061
+ // headers,
1062
+ // statusCode: 404,
1063
+ // });
1064
+ // }
1065
+ // });
1066
+ // }
1067
+ // });
1068
+ // }
1069
+ };
794
1070
 
795
- port = p;
796
- ip = "127.0.0.1";
797
- proto = "https";
798
- rootUrl = `${proto}://${ip}:${port}`;
799
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} server URL ${rootUrl}`);
1071
+ // NO_HTTP_REMOVE
1072
+ // expressApp = express();
1073
+ // // expressApp.enable('strict routing');
1074
+ // // expressApp.use("/", (req, res, next) => {
1075
+ // // if (LOG_DEBUG) console.log("HTTP: " + req.url);
1076
+ // // next();
1077
+ // // });
1078
+ // expressApp.basedir = basedir;
1079
+ // expressApp.use("/", (req, res, next) => {
1080
+ // next();
1081
+ // });
1082
+ // if (isDev) { // handle WebInspector JS maps etc.
1083
+ // expressApp.use("/", (req, res, next) => {
1084
+ // });
1085
+ // }
800
1086
 
801
- resolve();
802
- });
803
- }).catch((err) => {
804
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} generateSelfSignedData error!`);
805
- if (LOG_DEBUG) console.log(err);
806
- httpServer = expressApp.listen(port, () => {
807
- const p = httpServer.address().port;
808
-
809
- port = p;
810
- ip = "127.0.0.1";
811
- proto = "http";
812
- rootUrl = `${proto}://${ip}:${port}`;
813
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} server URL ${rootUrl}`);
814
-
815
- resolve();
816
- });
817
- });
818
- }
1087
+ // // https://expressjs.com/en/4x/api.html#express.static
1088
+ // const staticOptions = {
1089
+ // dotfiles: "ignore",
1090
+ // etag: true,
1091
+ // // fallthrough: false,
1092
+ // immutable: true,
1093
+ // // index: "index.html",
1094
+ // maxAge: "1d",
1095
+ // redirect: false,
1096
+ // // extensions: ["css", "otf"],
1097
+ // // setHeaders: (res, _path, _stat) => {
1098
+ // // // res.set('x-timestamp', Date.now())
1099
+ // // setResponseCORS(res);
1100
+ // // },
1101
+ // };
1102
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} HTTP static path ${basedir}`);
1103
+ // expressApp.use("/", express.static(basedir, staticOptions));
1104
+
1105
+ // const startHttp = function () {
1106
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner generateSelfSignedData...`);
1107
+ // generateSelfSignedData().then((certData) => {
1108
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner generateSelfSignedData OK.`);
1109
+
1110
+ // httpServer = https.createServer({ key: certData.private, cert: certData.cert }, expressApp).listen(port, () => {
1111
+ // const p = httpServer.address().port;
1112
+
1113
+ // port = p;
1114
+ // ip = "127.0.0.1";
1115
+ // proto = "https";
1116
+ // rootUrl = `${proto}://${ip}:${port}`;
1117
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} server URL ${rootUrl}`);
1118
+
1119
+ // resolve();
1120
+ // });
1121
+ // }).catch((err) => {
1122
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} generateSelfSignedData error!`);
1123
+ // if (LOG_DEBUG) console.log(err);
1124
+ // httpServer = expressApp.listen(port, () => {
1125
+ // const p = httpServer.address().port;
1126
+
1127
+ // port = p;
1128
+ // ip = "127.0.0.1";
1129
+ // proto = "http";
1130
+ // rootUrl = `${proto}://${ip}:${port}`;
1131
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} server URL ${rootUrl}`);
1132
+
1133
+ // resolve();
1134
+ // });
1135
+ // });
1136
+ // }
819
1137
 
820
- portfinder.getPortPromise().then((p) => {
821
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner HTTP port ${p}`);
822
- port = p;
823
- startHttp();
824
- }).catch((err) => {
825
- if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner HTTP port error!`);
826
- console.log(err);
827
- port = 3000;
828
- startHttp();
829
- });
830
- });
1138
+ // portfinder.getPortPromise().then((p) => {
1139
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner HTTP port ${p}`);
1140
+ // port = p;
1141
+ // startHttp();
1142
+ // }).catch((err) => {
1143
+ // if (LOG_DEBUG) console.log(`${ACE_LOG_PREFIX} axeRunner HTTP port error!`);
1144
+ // console.log(err);
1145
+ // port = 3000;
1146
+ // startHttp();
1147
+ // });
1148
+ // });
831
1149
  }
832
1150
 
833
1151
  function prepareLaunch(eventEmmitter, CONCURRENT_INSTANCES) {
834
-
835
1152
  eventEmmitter.on('AXE_RUNNER_LAUNCH', (event, arg) => {
836
1153
  // const payload = eventEmmitter.ace_notElectronIpcMainRenderer ? event : arg;
837
1154
  const sender = eventEmmitter.ace_notElectronIpcMainRenderer ? eventEmmitter : event.sender;