javascript-solid-server 0.0.148 → 0.0.150
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/.claude/settings.local.json +5 -1
- package/bin/jss.js +1 -1
- package/package.json +1 -1
- package/src/auth/middleware.js +7 -2
- package/test/subdomain-base-files.test.js +109 -0
|
@@ -351,7 +351,11 @@
|
|
|
351
351
|
"Read(//usr/local/lib/node_modules/gitmark-test/**)",
|
|
352
352
|
"WebFetch(domain:nip98.com)",
|
|
353
353
|
"WebFetch(domain:htmlpreview.github.io)",
|
|
354
|
-
"WebFetch(domain:timbl.solidcommunity.net)"
|
|
354
|
+
"WebFetch(domain:timbl.solidcommunity.net)",
|
|
355
|
+
"Read(//home/melvin/remote/github.com/solid-helper/core/**)",
|
|
356
|
+
"Bash(curl -s https://www.gnu.org/licenses/agpl-3.0.txt)",
|
|
357
|
+
"Bash(cat LICENSE.full)",
|
|
358
|
+
"Bash(rm LICENSE.full)"
|
|
355
359
|
]
|
|
356
360
|
}
|
|
357
361
|
}
|
package/bin/jss.js
CHANGED
|
@@ -327,7 +327,7 @@ const inviteCmd = program
|
|
|
327
327
|
inviteCmd
|
|
328
328
|
.command('create')
|
|
329
329
|
.description('Create a new invite code')
|
|
330
|
-
.option('-u, --uses <number>', 'Maximum uses (default: 1)', parseInt, 1)
|
|
330
|
+
.option('-u, --uses <number>', 'Maximum uses (default: 1)', (v) => parseInt(v, 10), 1)
|
|
331
331
|
.option('-n, --note <text>', 'Optional note/description')
|
|
332
332
|
.option('-r, --root <path>', 'Data directory')
|
|
333
333
|
.action(async (options) => {
|
package/package.json
CHANGED
package/src/auth/middleware.js
CHANGED
|
@@ -23,13 +23,18 @@ import { generateDatabrowserHtml, generateModuleDatabrowserHtml } from '../mashl
|
|
|
23
23
|
* @param {string} urlPath - URL path (e.g. /alice/public/file.ttl)
|
|
24
24
|
* @returns {string} Normalized resource URL
|
|
25
25
|
*/
|
|
26
|
-
function buildResourceUrl(request, urlPath) {
|
|
26
|
+
export function buildResourceUrl(request, urlPath) {
|
|
27
27
|
// Use request.headers.host (includes port) instead of request.hostname (strips port)
|
|
28
28
|
const host = request.headers.host || request.hostname;
|
|
29
29
|
if (request.subdomainsEnabled && request.baseDomain &&
|
|
30
30
|
request.hostname === request.baseDomain && !request.podName) {
|
|
31
31
|
const pathMatch = urlPath.match(/^\/([^/]+)(\/.*)?$/);
|
|
32
|
-
if
|
|
32
|
+
// Treat a path segment as a pod name only if it looks like one:
|
|
33
|
+
// - not a dotfile (.well-known, .acl, .meta, ...)
|
|
34
|
+
// - no dot (pod names are DNS labels; file names have extensions)
|
|
35
|
+
// This avoids rewriting /mashlib.js to https://mashlib.js.basedomain/
|
|
36
|
+
// which would fail WAC against the base domain's ACL. (#307)
|
|
37
|
+
if (pathMatch && !pathMatch[1].startsWith('.') && !pathMatch[1].includes('.')) {
|
|
33
38
|
const podName = pathMatch[1];
|
|
34
39
|
const remainder = pathMatch[2] || '/';
|
|
35
40
|
return `${request.protocol}://${podName}.${request.baseDomain}${remainder}`;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for #307 — buildResourceUrl rewriting the base-domain
|
|
3
|
+
* root file paths into non-existent pod subdomains.
|
|
4
|
+
*
|
|
5
|
+
* Unit tests against buildResourceUrl directly, since Node's fetch() overrides
|
|
6
|
+
* the Host header with the TCP target, which makes end-to-end tests of
|
|
7
|
+
* subdomain routing impossible without a real reverse proxy.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it } from 'node:test';
|
|
11
|
+
import assert from 'node:assert';
|
|
12
|
+
import { buildResourceUrl } from '../src/auth/middleware.js';
|
|
13
|
+
|
|
14
|
+
function makeRequest({ hostname, baseDomain, subdomainsEnabled = true, podName = null, protocol = 'https' }) {
|
|
15
|
+
return {
|
|
16
|
+
protocol,
|
|
17
|
+
hostname,
|
|
18
|
+
headers: { host: hostname },
|
|
19
|
+
subdomainsEnabled,
|
|
20
|
+
baseDomain,
|
|
21
|
+
podName
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('buildResourceUrl — base-domain files (#307)', () => {
|
|
26
|
+
const baseDomain = 'example.com';
|
|
27
|
+
|
|
28
|
+
it('base-domain root (/) — no rewrite', () => {
|
|
29
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
30
|
+
assert.strictEqual(buildResourceUrl(req, '/'), 'https://example.com/');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('base-domain /welcome.js — no rewrite (filename has extension)', () => {
|
|
34
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
35
|
+
assert.strictEqual(buildResourceUrl(req, '/welcome.js'), 'https://example.com/welcome.js');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('base-domain /mashlib.js — no rewrite', () => {
|
|
39
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
40
|
+
assert.strictEqual(buildResourceUrl(req, '/mashlib.js'), 'https://example.com/mashlib.js');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('base-domain /terms.html — no rewrite', () => {
|
|
44
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
45
|
+
assert.strictEqual(buildResourceUrl(req, '/terms.html'), 'https://example.com/terms.html');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('base-domain /.well-known/foo — no rewrite (leading dot)', () => {
|
|
49
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
50
|
+
assert.strictEqual(
|
|
51
|
+
buildResourceUrl(req, '/.well-known/foo'),
|
|
52
|
+
'https://example.com/.well-known/foo'
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('buildResourceUrl — pod routing still works', () => {
|
|
58
|
+
const baseDomain = 'example.com';
|
|
59
|
+
|
|
60
|
+
it('base-domain /alice/ — rewrites to alice.example.com (no dot → pod name)', () => {
|
|
61
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
62
|
+
assert.strictEqual(buildResourceUrl(req, '/alice/'), 'https://alice.example.com/');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('base-domain /alice — rewrites (bare pod-root without trailing slash)', () => {
|
|
66
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
67
|
+
assert.strictEqual(buildResourceUrl(req, '/alice'), 'https://alice.example.com/');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('base-domain /alice/profile/card.jsonld — rewrites to alice.example.com/profile/card.jsonld', () => {
|
|
71
|
+
const req = makeRequest({ hostname: baseDomain, baseDomain });
|
|
72
|
+
assert.strictEqual(
|
|
73
|
+
buildResourceUrl(req, '/alice/profile/card.jsonld'),
|
|
74
|
+
'https://alice.example.com/profile/card.jsonld'
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('already-on-subdomain request — no rewrite (hostname !== baseDomain)', () => {
|
|
79
|
+
const req = makeRequest({
|
|
80
|
+
hostname: 'alice.example.com',
|
|
81
|
+
baseDomain,
|
|
82
|
+
podName: 'alice'
|
|
83
|
+
});
|
|
84
|
+
assert.strictEqual(
|
|
85
|
+
buildResourceUrl(req, '/profile/card.jsonld'),
|
|
86
|
+
'https://alice.example.com/profile/card.jsonld'
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe('buildResourceUrl — subdomain mode disabled', () => {
|
|
92
|
+
it('no rewrite when subdomainsEnabled is false', () => {
|
|
93
|
+
const req = makeRequest({
|
|
94
|
+
hostname: 'example.com',
|
|
95
|
+
baseDomain: 'example.com',
|
|
96
|
+
subdomainsEnabled: false
|
|
97
|
+
});
|
|
98
|
+
assert.strictEqual(buildResourceUrl(req, '/alice/'), 'https://example.com/alice/');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('no rewrite when baseDomain is not set', () => {
|
|
102
|
+
const req = makeRequest({
|
|
103
|
+
hostname: 'example.com',
|
|
104
|
+
baseDomain: null,
|
|
105
|
+
subdomainsEnabled: true
|
|
106
|
+
});
|
|
107
|
+
assert.strictEqual(buildResourceUrl(req, '/alice/'), 'https://example.com/alice/');
|
|
108
|
+
});
|
|
109
|
+
});
|