koa-classic-server 1.1.0 → 2.0.0
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/BENCHMARKS.md +317 -0
- package/CHANGELOG.md +181 -0
- package/CREATE_RELEASE.sh +53 -0
- package/DEBUG_REPORT.md +593 -0
- package/DOCUMENTATION.md +1585 -0
- package/EXAMPLES_INDEX_OPTION.md +395 -0
- package/INDEX_OPTION_PRIORITY.md +527 -0
- package/LICENSE +21 -0
- package/OPTIMIZATION_HTTP_CACHING.md +687 -0
- package/PERFORMANCE_ANALYSIS.md +839 -0
- package/PERFORMANCE_COMPARISON.md +388 -0
- package/README.md +278 -103
- package/__tests__/index-option.test.js +447 -0
- package/__tests__/index.test.js +15 -11
- package/__tests__/performance.test.js +301 -0
- package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +1 -0
- package/__tests__/security.test.js +336 -0
- package/benchmark-results-baseline-v1.2.0.txt +354 -0
- package/benchmark-results-optimized-v2.0.0.txt +354 -0
- package/benchmark.js +239 -0
- package/demo-regex-index.js +140 -0
- package/index.cjs +386 -156
- package/jest.config.js +18 -0
- package/package.json +18 -5
- package/publish-to-npm.sh +65 -0
- package/scripts/setup-benchmark.js +178 -0
- package/test-regex-quick.js +158 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Index Option Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for the new index option that supports:
|
|
5
|
+
* - String (backward compatible)
|
|
6
|
+
* - Array of strings
|
|
7
|
+
* - Array of RegExp
|
|
8
|
+
* - Mixed array (strings + RegExp)
|
|
9
|
+
* - Priority handling (first match wins)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const Koa = require('koa');
|
|
13
|
+
const supertest = require('supertest');
|
|
14
|
+
const koaClassicServer = require('../index.cjs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
|
|
18
|
+
describe('Enhanced Index Option Tests', () => {
|
|
19
|
+
let app;
|
|
20
|
+
let server;
|
|
21
|
+
let tempDir;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
// Create temporary test directory
|
|
25
|
+
tempDir = path.join(__dirname, 'temp-index-test');
|
|
26
|
+
if (!fs.existsSync(tempDir)) {
|
|
27
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
// Cleanup
|
|
33
|
+
if (server) {
|
|
34
|
+
server.close();
|
|
35
|
+
}
|
|
36
|
+
// Remove temp directory
|
|
37
|
+
if (fs.existsSync(tempDir)) {
|
|
38
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('Backward Compatibility - String index', () => {
|
|
43
|
+
test('String: "index.html" should work as before', async () => {
|
|
44
|
+
// Create index.html
|
|
45
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>Index HTML</h1>');
|
|
46
|
+
|
|
47
|
+
app = new Koa();
|
|
48
|
+
app.use(koaClassicServer(tempDir, { index: 'index.html' }));
|
|
49
|
+
server = app.listen();
|
|
50
|
+
|
|
51
|
+
const res = await supertest(server).get('/');
|
|
52
|
+
expect(res.status).toBe(200);
|
|
53
|
+
expect(res.text).toContain('Index HTML');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('Empty string should show directory listing', async () => {
|
|
57
|
+
fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
|
|
58
|
+
|
|
59
|
+
app = new Koa();
|
|
60
|
+
app.use(koaClassicServer(tempDir, { index: '' }));
|
|
61
|
+
server = app.listen();
|
|
62
|
+
|
|
63
|
+
const res = await supertest(server).get('/');
|
|
64
|
+
expect(res.status).toBe(200);
|
|
65
|
+
expect(res.text).toContain('Index of');
|
|
66
|
+
expect(res.text).toContain('test.txt');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('Array of Strings - Priority order', () => {
|
|
71
|
+
test('Priority order - index1.html searched before index2.html', async () => {
|
|
72
|
+
// Create both files with distinctive content
|
|
73
|
+
fs.writeFileSync(path.join(tempDir, 'index1.html'), '<h1>FILE 1 - FIRST PRIORITY</h1>');
|
|
74
|
+
fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>FILE 2 - SECOND PRIORITY</h1>');
|
|
75
|
+
fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>FILE 3 - THIRD PRIORITY</h1>');
|
|
76
|
+
|
|
77
|
+
app = new Koa();
|
|
78
|
+
app.use(koaClassicServer(tempDir, {
|
|
79
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
80
|
+
}));
|
|
81
|
+
server = app.listen();
|
|
82
|
+
|
|
83
|
+
const res = await supertest(server).get('/');
|
|
84
|
+
expect(res.status).toBe(200);
|
|
85
|
+
// Must serve index1.html (first in array)
|
|
86
|
+
expect(res.text).toContain('FILE 1 - FIRST PRIORITY');
|
|
87
|
+
// Must NOT serve index2.html or index3.html
|
|
88
|
+
expect(res.text).not.toContain('FILE 2');
|
|
89
|
+
expect(res.text).not.toContain('FILE 3');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('Priority order - index2.html served when index1.html missing', async () => {
|
|
93
|
+
// Only create index2.html and index3.html (index1.html missing)
|
|
94
|
+
fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>FILE 2 - NOW FIRST AVAILABLE</h1>');
|
|
95
|
+
fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>FILE 3 - STILL THIRD</h1>');
|
|
96
|
+
|
|
97
|
+
app = new Koa();
|
|
98
|
+
app.use(koaClassicServer(tempDir, {
|
|
99
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
100
|
+
}));
|
|
101
|
+
server = app.listen();
|
|
102
|
+
|
|
103
|
+
const res = await supertest(server).get('/');
|
|
104
|
+
expect(res.status).toBe(200);
|
|
105
|
+
// Must serve index2.html (first available in array)
|
|
106
|
+
expect(res.text).toContain('FILE 2 - NOW FIRST AVAILABLE');
|
|
107
|
+
// Must NOT serve index3.html
|
|
108
|
+
expect(res.text).not.toContain('FILE 3');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test('First match wins - index.html over index.htm', async () => {
|
|
112
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>This is HTML version</h1>');
|
|
113
|
+
fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>This is HTM version</h1>');
|
|
114
|
+
|
|
115
|
+
app = new Koa();
|
|
116
|
+
app.use(koaClassicServer(tempDir, {
|
|
117
|
+
index: ['index.html', 'index.htm']
|
|
118
|
+
}));
|
|
119
|
+
server = app.listen();
|
|
120
|
+
|
|
121
|
+
const res = await supertest(server).get('/');
|
|
122
|
+
expect(res.status).toBe(200);
|
|
123
|
+
expect(res.text).toContain('This is HTML version');
|
|
124
|
+
expect(res.text).not.toContain('This is HTM version');
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('First match wins - index.htm when index.html missing', async () => {
|
|
128
|
+
fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
|
|
129
|
+
fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>Default</h1>');
|
|
130
|
+
|
|
131
|
+
app = new Koa();
|
|
132
|
+
app.use(koaClassicServer(tempDir, {
|
|
133
|
+
index: ['index.html', 'index.htm', 'default.html']
|
|
134
|
+
}));
|
|
135
|
+
server = app.listen();
|
|
136
|
+
|
|
137
|
+
const res = await supertest(server).get('/');
|
|
138
|
+
expect(res.status).toBe(200);
|
|
139
|
+
expect(res.text).toContain('HTM');
|
|
140
|
+
expect(res.text).not.toContain('Default');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test('Falls back to directory listing when no match', async () => {
|
|
144
|
+
fs.writeFileSync(path.join(tempDir, 'other.html'), '<h1>Other</h1>');
|
|
145
|
+
|
|
146
|
+
app = new Koa();
|
|
147
|
+
app.use(koaClassicServer(tempDir, {
|
|
148
|
+
index: ['index.html', 'index.htm']
|
|
149
|
+
}));
|
|
150
|
+
server = app.listen();
|
|
151
|
+
|
|
152
|
+
const res = await supertest(server).get('/');
|
|
153
|
+
expect(res.status).toBe(200);
|
|
154
|
+
expect(res.text).toContain('Index of');
|
|
155
|
+
expect(res.text).toContain('other.html');
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
describe('Array of RegExp - Case insensitive matching', () => {
|
|
160
|
+
test('Priority order - First RegExp pattern searched before second', async () => {
|
|
161
|
+
// Create files that match different patterns
|
|
162
|
+
fs.writeFileSync(path.join(tempDir, 'index1.html'), '<h1>PATTERN 1 MATCH</h1>');
|
|
163
|
+
fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>PATTERN 2 MATCH</h1>');
|
|
164
|
+
fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>PATTERN 3 MATCH</h1>');
|
|
165
|
+
|
|
166
|
+
app = new Koa();
|
|
167
|
+
app.use(koaClassicServer(tempDir, {
|
|
168
|
+
index: [
|
|
169
|
+
/index1\.html/i, // First pattern - should match index1.html
|
|
170
|
+
/index2\.html/i, // Second pattern - should be skipped
|
|
171
|
+
/index3\.html/i // Third pattern - should be skipped
|
|
172
|
+
]
|
|
173
|
+
}));
|
|
174
|
+
server = app.listen();
|
|
175
|
+
|
|
176
|
+
const res = await supertest(server).get('/');
|
|
177
|
+
expect(res.status).toBe(200);
|
|
178
|
+
// Must serve index1.html (first RegExp match)
|
|
179
|
+
expect(res.text).toContain('PATTERN 1 MATCH');
|
|
180
|
+
// Must NOT serve index2.html or index3.html
|
|
181
|
+
expect(res.text).not.toContain('PATTERN 2');
|
|
182
|
+
expect(res.text).not.toContain('PATTERN 3');
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('Priority order - Second RegExp when first does not match', async () => {
|
|
186
|
+
// index1.html does NOT exist, so first pattern won't match
|
|
187
|
+
fs.writeFileSync(path.join(tempDir, 'index2.html'), '<h1>PATTERN 2 NOW FIRST</h1>');
|
|
188
|
+
fs.writeFileSync(path.join(tempDir, 'index3.html'), '<h1>PATTERN 3 STILL THIRD</h1>');
|
|
189
|
+
|
|
190
|
+
app = new Koa();
|
|
191
|
+
app.use(koaClassicServer(tempDir, {
|
|
192
|
+
index: [
|
|
193
|
+
/index1\.html/i, // First pattern - no match (file doesn't exist)
|
|
194
|
+
/index2\.html/i, // Second pattern - should match
|
|
195
|
+
/index3\.html/i // Third pattern - should be skipped
|
|
196
|
+
]
|
|
197
|
+
}));
|
|
198
|
+
server = app.listen();
|
|
199
|
+
|
|
200
|
+
const res = await supertest(server).get('/');
|
|
201
|
+
expect(res.status).toBe(200);
|
|
202
|
+
// Must serve index2.html (first available match)
|
|
203
|
+
expect(res.text).toContain('PATTERN 2 NOW FIRST');
|
|
204
|
+
// Must NOT serve index3.html
|
|
205
|
+
expect(res.text).not.toContain('PATTERN 3');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('Priority order - Broader pattern searched before narrower pattern', async () => {
|
|
209
|
+
// Create multiple files
|
|
210
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML FILE</h1>');
|
|
211
|
+
fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM FILE</h1>');
|
|
212
|
+
fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>DEFAULT FILE</h1>');
|
|
213
|
+
|
|
214
|
+
app = new Koa();
|
|
215
|
+
app.use(koaClassicServer(tempDir, {
|
|
216
|
+
index: [
|
|
217
|
+
/index\.(html|htm)/i, // Broader pattern first - matches both .html and .htm
|
|
218
|
+
/default\.html/i // Narrower pattern second - should be skipped
|
|
219
|
+
]
|
|
220
|
+
}));
|
|
221
|
+
server = app.listen();
|
|
222
|
+
|
|
223
|
+
const res = await supertest(server).get('/');
|
|
224
|
+
expect(res.status).toBe(200);
|
|
225
|
+
// Must serve one of: index.html or index.htm (first pattern match)
|
|
226
|
+
expect(res.text).toMatch(/HTML FILE|HTM FILE/);
|
|
227
|
+
// Must NOT serve default.html
|
|
228
|
+
expect(res.text).not.toContain('DEFAULT FILE');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('RegExp case-insensitive: /index\\.html/i matches INDEX.HTML', async () => {
|
|
232
|
+
fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>UPPERCASE INDEX</h1>');
|
|
233
|
+
|
|
234
|
+
app = new Koa();
|
|
235
|
+
app.use(koaClassicServer(tempDir, {
|
|
236
|
+
index: [/index\.html/i]
|
|
237
|
+
}));
|
|
238
|
+
server = app.listen();
|
|
239
|
+
|
|
240
|
+
const res = await supertest(server).get('/');
|
|
241
|
+
expect(res.status).toBe(200);
|
|
242
|
+
expect(res.text).toContain('UPPERCASE INDEX');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test('RegExp case-insensitive: matches index.HTML, Index.html, INDEX.html', async () => {
|
|
246
|
+
fs.writeFileSync(path.join(tempDir, 'Index.Html'), '<h1>Mixed Case Index</h1>');
|
|
247
|
+
|
|
248
|
+
app = new Koa();
|
|
249
|
+
app.use(koaClassicServer(tempDir, {
|
|
250
|
+
index: [/index\.html/i]
|
|
251
|
+
}));
|
|
252
|
+
server = app.listen();
|
|
253
|
+
|
|
254
|
+
const res = await supertest(server).get('/');
|
|
255
|
+
expect(res.status).toBe(200);
|
|
256
|
+
expect(res.text).toContain('Mixed Case Index');
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('RegExp pattern: /index\\.(html|htm)/i matches both extensions', async () => {
|
|
260
|
+
fs.writeFileSync(path.join(tempDir, 'index.HTM'), '<h1>HTM</h1>');
|
|
261
|
+
|
|
262
|
+
app = new Koa();
|
|
263
|
+
app.use(koaClassicServer(tempDir, {
|
|
264
|
+
index: [/index\.(html|htm)/i]
|
|
265
|
+
}));
|
|
266
|
+
server = app.listen();
|
|
267
|
+
|
|
268
|
+
const res = await supertest(server).get('/');
|
|
269
|
+
expect(res.status).toBe(200);
|
|
270
|
+
expect(res.text).toContain('HTM');
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test('RegExp pattern: /index\\.ejs/i matches INDEX.EJS', async () => {
|
|
274
|
+
fs.writeFileSync(path.join(tempDir, 'INDEX.EJS'), 'EJS content');
|
|
275
|
+
|
|
276
|
+
app = new Koa();
|
|
277
|
+
app.use(koaClassicServer(tempDir, {
|
|
278
|
+
index: [/index\.ejs/i]
|
|
279
|
+
}));
|
|
280
|
+
server = app.listen();
|
|
281
|
+
|
|
282
|
+
const res = await supertest(server).get('/');
|
|
283
|
+
expect(res.status).toBe(200);
|
|
284
|
+
expect(res.text).toContain('EJS content');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
describe('Mixed Array - Strings + RegExp', () => {
|
|
289
|
+
test('Priority: String before RegExp', async () => {
|
|
290
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML Exact</h1>');
|
|
291
|
+
fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>HTML Uppercase</h1>');
|
|
292
|
+
|
|
293
|
+
app = new Koa();
|
|
294
|
+
app.use(koaClassicServer(tempDir, {
|
|
295
|
+
index: ['index.html', /INDEX\.HTML/]
|
|
296
|
+
}));
|
|
297
|
+
server = app.listen();
|
|
298
|
+
|
|
299
|
+
const res = await supertest(server).get('/');
|
|
300
|
+
expect(res.status).toBe(200);
|
|
301
|
+
expect(res.text).toContain('HTML Exact');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
test('Falls back to RegExp when string doesn\'t match', async () => {
|
|
305
|
+
fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>HTML Uppercase</h1>');
|
|
306
|
+
|
|
307
|
+
app = new Koa();
|
|
308
|
+
app.use(koaClassicServer(tempDir, {
|
|
309
|
+
index: ['index.html', /INDEX\.HTML/i]
|
|
310
|
+
}));
|
|
311
|
+
server = app.listen();
|
|
312
|
+
|
|
313
|
+
const res = await supertest(server).get('/');
|
|
314
|
+
expect(res.status).toBe(200);
|
|
315
|
+
expect(res.text).toContain('HTML Uppercase');
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('Complex example: Mixed priorities', async () => {
|
|
319
|
+
fs.writeFileSync(path.join(tempDir, 'default.html'), '<h1>Default</h1>');
|
|
320
|
+
fs.writeFileSync(path.join(tempDir, 'INDEX.HTML'), '<h1>Uppercase Index</h1>');
|
|
321
|
+
|
|
322
|
+
app = new Koa();
|
|
323
|
+
app.use(koaClassicServer(tempDir, {
|
|
324
|
+
index: [
|
|
325
|
+
'index.html', // 1. Exact match (case-sensitive)
|
|
326
|
+
/index\.htm/i, // 2. Case-insensitive index.htm(l)
|
|
327
|
+
'default.html' // 3. default.html
|
|
328
|
+
]
|
|
329
|
+
}));
|
|
330
|
+
server = app.listen();
|
|
331
|
+
|
|
332
|
+
const res = await supertest(server).get('/');
|
|
333
|
+
expect(res.status).toBe(200);
|
|
334
|
+
// Should match #2 (INDEX.HTML via regex)
|
|
335
|
+
expect(res.text).toContain('Uppercase Index');
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
describe('Real-world use cases', () => {
|
|
340
|
+
test('Apache-like: index.html, index.htm, index.php', async () => {
|
|
341
|
+
fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
|
|
342
|
+
|
|
343
|
+
app = new Koa();
|
|
344
|
+
app.use(koaClassicServer(tempDir, {
|
|
345
|
+
index: ['index.html', 'index.htm', 'index.php']
|
|
346
|
+
}));
|
|
347
|
+
server = app.listen();
|
|
348
|
+
|
|
349
|
+
const res = await supertest(server).get('/');
|
|
350
|
+
expect(res.status).toBe(200);
|
|
351
|
+
expect(res.text).toContain('HTM');
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('Template engines: index.ejs, index.pug, index.html', async () => {
|
|
355
|
+
fs.writeFileSync(path.join(tempDir, 'index.pug'), 'pug content');
|
|
356
|
+
|
|
357
|
+
app = new Koa();
|
|
358
|
+
app.use(koaClassicServer(tempDir, {
|
|
359
|
+
index: ['index.ejs', 'index.pug', 'index.html']
|
|
360
|
+
}));
|
|
361
|
+
server = app.listen();
|
|
362
|
+
|
|
363
|
+
const res = await supertest(server).get('/');
|
|
364
|
+
expect(res.status).toBe(200);
|
|
365
|
+
expect(res.text).toContain('pug content');
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test('Case-insensitive filesystem (Windows-like): matches any case', async () => {
|
|
369
|
+
fs.writeFileSync(path.join(tempDir, 'InDeX.HtMl'), '<h1>Mixed Case</h1>');
|
|
370
|
+
|
|
371
|
+
app = new Koa();
|
|
372
|
+
app.use(koaClassicServer(tempDir, {
|
|
373
|
+
index: [/index\.html/i]
|
|
374
|
+
}));
|
|
375
|
+
server = app.listen();
|
|
376
|
+
|
|
377
|
+
const res = await supertest(server).get('/');
|
|
378
|
+
expect(res.status).toBe(200);
|
|
379
|
+
expect(res.text).toContain('Mixed Case');
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
describe('Edge cases', () => {
|
|
384
|
+
test('Empty array shows directory listing', async () => {
|
|
385
|
+
fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
|
|
386
|
+
|
|
387
|
+
app = new Koa();
|
|
388
|
+
app.use(koaClassicServer(tempDir, { index: [] }));
|
|
389
|
+
server = app.listen();
|
|
390
|
+
|
|
391
|
+
const res = await supertest(server).get('/');
|
|
392
|
+
expect(res.status).toBe(200);
|
|
393
|
+
expect(res.text).toContain('Index of');
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test('Invalid array elements are filtered out', async () => {
|
|
397
|
+
fs.writeFileSync(path.join(tempDir, 'test.txt'), 'test');
|
|
398
|
+
|
|
399
|
+
app = new Koa();
|
|
400
|
+
app.use(koaClassicServer(tempDir, {
|
|
401
|
+
index: ['index.html', 123, null, /notfound/] // Invalid: 123, null; /notfound/ won't match
|
|
402
|
+
}));
|
|
403
|
+
server = app.listen();
|
|
404
|
+
|
|
405
|
+
const res = await supertest(server).get('/');
|
|
406
|
+
expect(res.status).toBe(200);
|
|
407
|
+
// Should show directory listing (no valid match)
|
|
408
|
+
expect(res.text).toContain('Index of');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test('RegExp matches first file when multiple match', async () => {
|
|
412
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<h1>HTML</h1>');
|
|
413
|
+
fs.writeFileSync(path.join(tempDir, 'index.htm'), '<h1>HTM</h1>');
|
|
414
|
+
|
|
415
|
+
app = new Koa();
|
|
416
|
+
app.use(koaClassicServer(tempDir, {
|
|
417
|
+
index: [/index\.(html|htm)/]
|
|
418
|
+
}));
|
|
419
|
+
server = app.listen();
|
|
420
|
+
|
|
421
|
+
const res = await supertest(server).get('/');
|
|
422
|
+
expect(res.status).toBe(200);
|
|
423
|
+
// Should match one of them (order depends on readdir)
|
|
424
|
+
expect(res.text).toMatch(/HTML|HTM/);
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe('Integration with existing index.html tests', () => {
|
|
429
|
+
test('Works with array index option for typical setup', async () => {
|
|
430
|
+
// Create typical index.html setup
|
|
431
|
+
fs.writeFileSync(path.join(tempDir, 'index.html'), '<!DOCTYPE html><html><body><h1>Welcome</h1></body></html>');
|
|
432
|
+
fs.writeFileSync(path.join(tempDir, 'other.txt'), 'other file');
|
|
433
|
+
|
|
434
|
+
app = new Koa();
|
|
435
|
+
app.use(koaClassicServer(tempDir, {
|
|
436
|
+
index: ['index.html', 'index.htm', 'default.html']
|
|
437
|
+
}));
|
|
438
|
+
server = app.listen();
|
|
439
|
+
|
|
440
|
+
const res = await supertest(server).get('/');
|
|
441
|
+
expect(res.status).toBe(200);
|
|
442
|
+
// Should find index.html
|
|
443
|
+
expect(res.text).toContain('Welcome');
|
|
444
|
+
expect(res.text).toContain('<!DOCTYPE html>');
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
});
|
package/__tests__/index.test.js
CHANGED
|
@@ -51,9 +51,9 @@ describe(` koaClassicServer options0: ${JSON.stringify(options0)}`, () => {
|
|
|
51
51
|
test('controllo che se chiamo un percorso che non esiste mi venga restituito l\'errore apropiato ', async () => {
|
|
52
52
|
// Effettua una richiesta GET sull'endpoint configurato (il prefisso)
|
|
53
53
|
const res = await supertest(server).get('/public/percorso_di_una_cartella_o_file_che_non_esiste_fbrojngbornbo/gbrtbbbrbr/tbrbr/rtbrtbrt');
|
|
54
|
-
expect(res.status).toBe(
|
|
54
|
+
expect(res.status).toBe(404); // FIX: Now returns proper 404 status
|
|
55
55
|
expect(res.type).toMatch(/text\/html/);// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
|
|
56
|
-
expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
|
|
56
|
+
expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
test('controllo che se l\'indirizzo non ricade nel urlPrefix allora debba essere passato al midlware successivo e se non c\'e allora errore 404 not founf', async () => {
|
|
@@ -96,9 +96,9 @@ describe(` koaClassicServer options1: ${JSON.stringify(options1)}`, () => {
|
|
|
96
96
|
test('controllo che se chiamo un percorso che non esiste mi venga restituito l\'errore apropiato [ANCHE SENZA URL PREFIX] ', async () => {
|
|
97
97
|
// Effettua una richiesta GET sull'endpoint configurato (il prefisso)
|
|
98
98
|
const res = await supertest(server).get('/BTBg h gh /percorso_di_una_cartella_o_file_che_non_esiste_fbrojngbornbo/gbrtbbbrbr/tbrbr/rtbrtbrt');
|
|
99
|
-
expect(res.status).toBe(
|
|
99
|
+
expect(res.status).toBe(404); // FIX: Now returns proper 404 status
|
|
100
100
|
expect(res.type).toMatch(/text\/html/);// type sta per mimetype .... restituisce text/plain anche se dovrebbe essere text/html
|
|
101
|
-
expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
|
|
101
|
+
expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
const testFnCallbacks = testAllPathByFileList(filesAndDirArray, () => server, options1);//Genera l'array di callback per i test
|
|
@@ -230,15 +230,13 @@ function requestedUrlNotFound() {
|
|
|
230
230
|
<html>
|
|
231
231
|
<head>
|
|
232
232
|
<meta charset="UTF-8">
|
|
233
|
-
<meta http-equiv="X-UA-Compatible">
|
|
233
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
234
234
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
235
235
|
<title>URL not found</title>
|
|
236
236
|
</head>
|
|
237
237
|
<body>
|
|
238
238
|
<h1>Not Found</h1>
|
|
239
|
-
|
|
240
239
|
<h3>The requested URL was not found on this server.</h3>
|
|
241
|
-
|
|
242
240
|
</body>
|
|
243
241
|
</html>
|
|
244
242
|
`;
|
|
@@ -259,17 +257,23 @@ function testAllPathByFileList(filesAndDirArray, getServer, options) {
|
|
|
259
257
|
const server = getServer(); // Usa il getter per ottenere il server al momento dell'esecuzione
|
|
260
258
|
const url = path.join(options.urlPrefix || '/', relativePath);
|
|
261
259
|
const res = await supertest(server).get(url);
|
|
262
|
-
|
|
260
|
+
|
|
263
261
|
// Se l'entry è un file, controlla il contenuto e il MIME type
|
|
264
262
|
if (entry.type === 'file') {
|
|
263
|
+
expect(res.status).toBe(200);
|
|
265
264
|
const content = fs.readFileSync(entry.fullPath, 'utf8');
|
|
266
265
|
expect(res.type).toBe(entry.mimeType);
|
|
267
266
|
expect(res.text).toBe(content);
|
|
268
267
|
} else {//è una directory
|
|
269
|
-
expect(res.type).toBe('text/html');
|
|
270
|
-
expect(res.text).toContain('<!DOCTYPE html>');
|
|
271
268
|
if( options.showDirContents === false ){
|
|
272
|
-
|
|
269
|
+
// FIX: Quando directory listing è disabilitato, restituisce 404
|
|
270
|
+
expect(res.status).toBe(404);
|
|
271
|
+
expect(res.type).toBe('text/html');
|
|
272
|
+
expect(res.text.replace(/\s/g, '')).toBe(requestedUrlNotFound().replace(/\s/g, '')); //.replace(/\s/g, '') --> rimuoce gli spazi bianchi e le tabulazioni , il server agiunge degli spazi all'inizio facendo fallire il controllo
|
|
273
|
+
} else {
|
|
274
|
+
expect(res.status).toBe(200);
|
|
275
|
+
expect(res.type).toBe('text/html');
|
|
276
|
+
expect(res.text).toContain('<!DOCTYPE html>');
|
|
273
277
|
}
|
|
274
278
|
}
|
|
275
279
|
}
|