roster-server 2.1.4 → 2.1.8
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/index.js +19 -0
- package/package.json +1 -1
- package/test/roster-server.test.js +43 -0
package/index.js
CHANGED
|
@@ -86,6 +86,14 @@ function buildCertLookupCandidates(servername) {
|
|
|
86
86
|
return candidates;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
function parseBooleanFlag(value, fallback = false) {
|
|
90
|
+
if (value === undefined || value === null || value === '') return fallback;
|
|
91
|
+
const normalized = String(value).trim().toLowerCase();
|
|
92
|
+
if (['1', 'true', 'yes', 'on'].includes(normalized)) return true;
|
|
93
|
+
if (['0', 'false', 'no', 'off'].includes(normalized)) return false;
|
|
94
|
+
return fallback;
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
// Virtual Server that completely isolates applications
|
|
90
98
|
class VirtualServer extends EventEmitter {
|
|
91
99
|
constructor(domain) {
|
|
@@ -222,6 +230,9 @@ class Roster {
|
|
|
222
230
|
this.maxLocalPort = options.maxLocalPort || 9999;
|
|
223
231
|
this.tlsMinVersion = options.tlsMinVersion ?? 'TLSv1.2';
|
|
224
232
|
this.tlsMaxVersion = options.tlsMaxVersion ?? 'TLSv1.3';
|
|
233
|
+
this.disableWildcard = options.disableWildcard !== undefined
|
|
234
|
+
? parseBooleanFlag(options.disableWildcard, false)
|
|
235
|
+
: parseBooleanFlag(process.env.ROSTER_DISABLE_WILDCARD, false);
|
|
225
236
|
|
|
226
237
|
const port = options.port === undefined ? 443 : options.port;
|
|
227
238
|
if (port === 80 && !this.local) {
|
|
@@ -299,6 +310,10 @@ class Roster {
|
|
|
299
310
|
|
|
300
311
|
if (siteApp) {
|
|
301
312
|
if (domain.startsWith('*.')) {
|
|
313
|
+
if (this.disableWildcard) {
|
|
314
|
+
log.warn(`⚠️ Wildcard site skipped (disableWildcard enabled): ${domain}`);
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
302
317
|
// Wildcard site: one handler for all subdomains (e.g. *.example.com)
|
|
303
318
|
this.domains.push(domain);
|
|
304
319
|
this.sites[domain] = siteApp;
|
|
@@ -513,6 +528,10 @@ class Roster {
|
|
|
513
528
|
const { domain, port } = this.parseDomainWithPort(domainString);
|
|
514
529
|
|
|
515
530
|
if (domain.startsWith('*.')) {
|
|
531
|
+
if (this.disableWildcard) {
|
|
532
|
+
log.warn(`⚠️ Wildcard registration ignored (disableWildcard enabled): ${domain}`);
|
|
533
|
+
return this;
|
|
534
|
+
}
|
|
516
535
|
const domainKey = port === this.defaultPort ? domain : `${domain}:${port}`;
|
|
517
536
|
this.domains.push(domain);
|
|
518
537
|
this.sites[domainKey] = requestHandler;
|
package/package.json
CHANGED
|
@@ -168,6 +168,14 @@ describe('Roster', () => {
|
|
|
168
168
|
roster.register('*.example.com', wildcardHandler);
|
|
169
169
|
assert.strictEqual(roster.getHandlerForHost('api.example.com'), exactHandler);
|
|
170
170
|
});
|
|
171
|
+
it('ignores wildcard registration when disableWildcard is true', () => {
|
|
172
|
+
const roster = new Roster({ local: true, disableWildcard: true });
|
|
173
|
+
const handler = () => {};
|
|
174
|
+
roster.register('*.example.com', handler);
|
|
175
|
+
assert.strictEqual(roster.sites['*.example.com'], undefined);
|
|
176
|
+
assert.strictEqual(roster.getHandlerForHost('api.example.com'), null);
|
|
177
|
+
assert.strictEqual(roster.wildcardZones.has('example.com'), false);
|
|
178
|
+
});
|
|
171
179
|
});
|
|
172
180
|
|
|
173
181
|
describe('getHandlerForPortData', () => {
|
|
@@ -290,6 +298,21 @@ describe('Roster', () => {
|
|
|
290
298
|
const roster = new Roster({ local: false, dnsChallenge: false });
|
|
291
299
|
assert.strictEqual(roster.dnsChallenge, null);
|
|
292
300
|
});
|
|
301
|
+
it('enables disableWildcard from constructor option', () => {
|
|
302
|
+
const roster = new Roster({ local: true, disableWildcard: true });
|
|
303
|
+
assert.strictEqual(roster.disableWildcard, true);
|
|
304
|
+
});
|
|
305
|
+
it('reads disableWildcard from env var', () => {
|
|
306
|
+
const previous = process.env.ROSTER_DISABLE_WILDCARD;
|
|
307
|
+
process.env.ROSTER_DISABLE_WILDCARD = '1';
|
|
308
|
+
try {
|
|
309
|
+
const roster = new Roster({ local: true });
|
|
310
|
+
assert.strictEqual(roster.disableWildcard, true);
|
|
311
|
+
} finally {
|
|
312
|
+
if (previous === undefined) delete process.env.ROSTER_DISABLE_WILDCARD;
|
|
313
|
+
else process.env.ROSTER_DISABLE_WILDCARD = previous;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
293
316
|
});
|
|
294
317
|
|
|
295
318
|
describe('register (normal domain)', () => {
|
|
@@ -470,6 +493,26 @@ describe('Roster loadSites', () => {
|
|
|
470
493
|
}
|
|
471
494
|
});
|
|
472
495
|
|
|
496
|
+
it('skips wildcard site from www when disableWildcard is true', async () => {
|
|
497
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'roster-test-'));
|
|
498
|
+
const wwwPath = path.join(tmpDir, 'www');
|
|
499
|
+
const siteDir = path.join(wwwPath, '*.wildcard.example');
|
|
500
|
+
fs.mkdirSync(siteDir, { recursive: true });
|
|
501
|
+
fs.writeFileSync(
|
|
502
|
+
path.join(siteDir, 'index.js'),
|
|
503
|
+
'module.exports = () => (req, res) => { res.writeHead(200); res.end("wildcard"); };',
|
|
504
|
+
'utf8'
|
|
505
|
+
);
|
|
506
|
+
try {
|
|
507
|
+
const roster = new Roster({ wwwPath, local: true, disableWildcard: true });
|
|
508
|
+
await roster.loadSites();
|
|
509
|
+
assert.strictEqual(roster.sites['*.wildcard.example'], undefined);
|
|
510
|
+
assert.strictEqual(roster.wildcardZones.has('wildcard.example'), false);
|
|
511
|
+
} finally {
|
|
512
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
|
|
473
516
|
it('does not throw when www path does not exist', async () => {
|
|
474
517
|
const roster = new Roster({
|
|
475
518
|
wwwPath: path.join(os.tmpdir(), 'roster-nonexistent-' + Date.now()),
|