koa-classic-server 3.0.0 ā 3.1.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/README.md +44 -120
- package/index.cjs +236 -21
- package/package.json +10 -5
- package/.github/workflows/npm-publish.yml +0 -98
- package/CLAUDE.md +0 -101
- package/__tests__/benchmark-results-baseline-v1.2.0.txt +0 -354
- package/__tests__/benchmark-results-optimized-v2.0.0.txt +0 -354
- package/__tests__/benchmark-results-v3.0.0.txt +0 -372
- package/__tests__/benchmark.js +0 -239
- package/__tests__/caching-headers.test.js +0 -556
- package/__tests__/compression-fixtures/data.json +0 -1
- package/__tests__/compression-fixtures/large.txt +0 -1
- package/__tests__/compression-fixtures/small.txt +0 -1
- package/__tests__/compression.test.js +0 -284
- package/__tests__/customTest/README.md +0 -6
- package/__tests__/customTest/loadConfig.util.js +0 -41
- package/__tests__/customTest/serversToLoad.util.js +0 -93
- package/__tests__/demo-regex-index.js +0 -140
- package/__tests__/deprecation-warnings.test.js +0 -105
- package/__tests__/directory-sorting-links.test.js +0 -135
- package/__tests__/dt-unknown.test.js +0 -635
- package/__tests__/ejs.test.js +0 -299
- package/__tests__/hidden-fixtures/.dot-dir/inside.txt +0 -1
- package/__tests__/hidden-fixtures/.env +0 -2
- package/__tests__/hidden-fixtures/.well-known/acme-challenge.txt +0 -1
- package/__tests__/hidden-fixtures/config/secrets/password.txt +0 -1
- package/__tests__/hidden-fixtures/data.key +0 -1
- package/__tests__/hidden-fixtures/file.secret +0 -1
- package/__tests__/hidden-fixtures/index.html +0 -1
- package/__tests__/hidden-fixtures/normal.txt +0 -1
- package/__tests__/hidden-fixtures/subdir/.env +0 -1
- package/__tests__/hidden-fixtures/subdir/regular.txt +0 -1
- package/__tests__/hidden-option.test.js +0 -407
- package/__tests__/hideExtension.test.js +0 -607
- package/__tests__/index-option.test.js +0 -449
- package/__tests__/index.test.js +0 -345
- package/__tests__/listing.test.js +0 -437
- package/__tests__/logger.test.js +0 -232
- package/__tests__/performance.test.js +0 -370
- package/__tests__/publicWwwTest/cartella/sottocartella/ciao.html +0 -11
- package/__tests__/publicWwwTest/cartella/sottocartella/provaEjs/testEjs.ejs +0 -11
- package/__tests__/publicWwwTest/cartella vuota con spazi nel nome/file con spazio nel nome .txt +0 -1
- package/__tests__/publicWwwTest/cartella vuota con spazi nel nome /file con spazio nel nome .txt +0 -1
- package/__tests__/publicWwwTest/ejs-templates/complex.ejs +0 -56
- package/__tests__/publicWwwTest/ejs-templates/index.ejs +0 -30
- package/__tests__/publicWwwTest/ejs-templates/simple.ejs +0 -13
- package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +0 -28
- package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +0 -26
- package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +0 -16
- package/__tests__/publicWwwTest/hideext-test/about/index.html +0 -1
- package/__tests__/publicWwwTest/hideext-test/about.EJS +0 -1
- package/__tests__/publicWwwTest/hideext-test/about.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/blog/articolo.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina +0 -1
- package/__tests__/publicWwwTest/hideext-test/conflict-test/pagina.ejs +0 -1
- package/__tests__/publicWwwTest/hideext-test/file.ejs.bak +0 -1
- package/__tests__/publicWwwTest/hideext-test/index.ejs +0 -2
- package/__tests__/publicWwwTest/hideext-test/photo.txt +0 -1
- package/__tests__/publicWwwTest/hideext-test/sezione/index.ejs +0 -1
- package/__tests__/publicWwwTest/hideext-test/style.css +0 -1
- package/__tests__/publicWwwTest/ile_vuoto.txt +0 -0
- package/__tests__/publicWwwTest/index.html +0 -11
- package/__tests__/publicWwwTest/prova file .txt +0 -2
- package/__tests__/publicWwwTest/semplicetxt.txt +0 -1
- package/__tests__/publicWwwTest/test-page.html +0 -1
- package/__tests__/publicWwwTest/test.txt +0 -1
- package/__tests__/range-fixtures/sample.txt +0 -1
- package/__tests__/range.test.js +0 -223
- package/__tests__/security-headers.test.js +0 -165
- package/__tests__/security.test.js +0 -322
- package/__tests__/server-cache-fixtures/large.txt +0 -1
- package/__tests__/server-cache-fixtures/small.txt +0 -1
- package/__tests__/server-cache.test.js +0 -594
- package/__tests__/setup-benchmark.js +0 -178
- package/__tests__/symlink.test.js +0 -441
- package/__tests__/template-timeout.test.js +0 -321
- package/__tests__/test-regex-quick.js +0 -158
- package/__tests__/useOriginalUrl.test.js +0 -213
- package/docs/ACTION_PLAN.md +0 -293
- package/docs/BENCHMARKS.md +0 -317
- package/docs/CHANGELOG.md +0 -880
- package/docs/CODE_REVIEW.md +0 -300
- package/docs/DEBUG_REPORT.md +0 -593
- package/docs/DOCUMENTATION.md +0 -1864
- package/docs/EXAMPLES_INDEX_OPTION.md +0 -395
- package/docs/FLOW_DIAGRAM.md +0 -954
- package/docs/INDEX_OPTION_PRIORITY.md +0 -527
- package/docs/OPTIMIZATION_HTTP_CACHING.md +0 -689
- package/docs/OPTIMIZATION_ROADMAP_for_V3.md +0 -864
- package/docs/PERFORMANCE_ANALYSIS.md +0 -839
- package/docs/PERFORMANCE_COMPARISON.md +0 -388
- package/docs/noteExports.md +0 -148
- package/docs/security_improvement_for_V3.md +0 -421
- package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +0 -1734
- package/docs/template-engine/esempi-incrementali.js +0 -192
- package/docs/template-engine/examples/esempio1-nessun-dato.ejs +0 -12
- package/docs/template-engine/examples/esempio2-una-variabile.ejs +0 -11
- package/docs/template-engine/examples/esempio3-piu-variabili.ejs +0 -15
- package/docs/template-engine/examples/esempio4-condizionale.ejs +0 -18
- package/docs/template-engine/examples/esempio5-loop.ejs +0 -18
- package/docs/template-engine/examples/index-esempi.html +0 -181
- package/docs/template-engine/examples/index.html +0 -40
- package/docs/template-engine/examples/test.ejs +0 -64
- package/eslint.config.mjs +0 -17
- package/jest.config.js +0 -18
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
const supertest = require('supertest');
|
|
2
|
-
const koaClassicServer = require('../index.cjs');
|
|
3
|
-
const Koa = require('koa');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
|
|
6
|
-
const root = path.join(__dirname, 'compression-fixtures');
|
|
7
|
-
|
|
8
|
-
// Fixtures:
|
|
9
|
-
// large.txt ā 2000 bytes of 'A' (text/plain, exceeds 1KB threshold)
|
|
10
|
-
// small.txt ā 4 bytes of 'tiny' (text/plain, below 1KB threshold)
|
|
11
|
-
// data.json ā 16 bytes '{"key":"value"}\n' (application/json, below threshold)
|
|
12
|
-
|
|
13
|
-
function createApp(opts = {}) {
|
|
14
|
-
const app = new Koa();
|
|
15
|
-
app.use(koaClassicServer(root, { dirListing: { enabled: false }, ...opts }));
|
|
16
|
-
return app.listen();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// āāā Default behaviour (compression enabled, serverCache enabled) āāāāāāāāāāāāā
|
|
20
|
-
|
|
21
|
-
describe('Compression ā default: br preferred', () => {
|
|
22
|
-
let server;
|
|
23
|
-
beforeAll(() => { server = createApp(); });
|
|
24
|
-
afterAll(() => server.close());
|
|
25
|
-
|
|
26
|
-
test('large.txt with Accept-Encoding: br ā brotli compressed', async () => {
|
|
27
|
-
const res = await supertest(server)
|
|
28
|
-
.get('/large.txt')
|
|
29
|
-
.set('Accept-Encoding', 'br');
|
|
30
|
-
expect(res.status).toBe(200);
|
|
31
|
-
expect(res.headers['content-encoding']).toBe('br');
|
|
32
|
-
expect(res.headers['vary']).toBe('Accept-Encoding');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test('large.txt with Accept-Encoding: gzip ā gzip compressed, body decompressed by supertest', async () => {
|
|
36
|
-
const res = await supertest(server)
|
|
37
|
-
.get('/large.txt')
|
|
38
|
-
.set('Accept-Encoding', 'gzip');
|
|
39
|
-
expect(res.status).toBe(200);
|
|
40
|
-
expect(res.headers['content-encoding']).toBe('gzip');
|
|
41
|
-
expect(res.headers['vary']).toBe('Accept-Encoding');
|
|
42
|
-
// supertest auto-decompresses gzip ā res.text is the original content
|
|
43
|
-
expect(res.text).toBe('A'.repeat(2000));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('large.txt with Accept-Encoding: br,gzip ā br preferred (higher priority)', async () => {
|
|
47
|
-
const res = await supertest(server)
|
|
48
|
-
.get('/large.txt')
|
|
49
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
50
|
-
expect(res.headers['content-encoding']).toBe('br');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Use 'identity' to prevent supertest's default Accept-Encoding from triggering compression
|
|
54
|
-
test('large.txt with Accept-Encoding: identity ā uncompressed', async () => {
|
|
55
|
-
const res = await supertest(server)
|
|
56
|
-
.get('/large.txt')
|
|
57
|
-
.set('Accept-Encoding', 'identity');
|
|
58
|
-
expect(res.status).toBe(200);
|
|
59
|
-
expect(res.headers['content-encoding']).toBeUndefined();
|
|
60
|
-
expect(res.headers['vary']).toBeUndefined();
|
|
61
|
-
expect(res.text).toBe('A'.repeat(2000));
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('Content-Length present on compressed response (serverCache)', async () => {
|
|
65
|
-
const res = await supertest(server)
|
|
66
|
-
.get('/large.txt')
|
|
67
|
-
.set('Accept-Encoding', 'gzip');
|
|
68
|
-
expect(res.headers['content-length']).toBeDefined();
|
|
69
|
-
expect(Number(res.headers['content-length'])).toBeGreaterThan(0);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('Compressed Content-Length is smaller than original file size', async () => {
|
|
73
|
-
const res = await supertest(server)
|
|
74
|
-
.get('/large.txt')
|
|
75
|
-
.set('Accept-Encoding', 'gzip');
|
|
76
|
-
expect(Number(res.headers['content-length'])).toBeLessThan(2000);
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
// āāā Threshold: files below threshold are served uncompressed āāāāāāāāāāāāāāāā
|
|
81
|
-
|
|
82
|
-
describe('Compression ā threshold (default 1024 bytes)', () => {
|
|
83
|
-
let server;
|
|
84
|
-
beforeAll(() => { server = createApp(); });
|
|
85
|
-
afterAll(() => server.close());
|
|
86
|
-
|
|
87
|
-
test('small.txt (4 bytes) below threshold ā no compression', async () => {
|
|
88
|
-
const res = await supertest(server)
|
|
89
|
-
.get('/small.txt')
|
|
90
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
91
|
-
expect(res.status).toBe(200);
|
|
92
|
-
expect(res.headers['content-encoding']).toBeUndefined();
|
|
93
|
-
expect(res.text).toBe('tiny');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('large.txt (2000 bytes) above threshold ā compressed', async () => {
|
|
97
|
-
const res = await supertest(server)
|
|
98
|
-
.get('/large.txt')
|
|
99
|
-
.set('Accept-Encoding', 'gzip');
|
|
100
|
-
expect(res.headers['content-encoding']).toBe('gzip');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('minFileSize: false ā compress regardless of size', async () => {
|
|
104
|
-
const s = createApp({ compression: { minFileSize: false } });
|
|
105
|
-
const res = await supertest(s)
|
|
106
|
-
.get('/small.txt')
|
|
107
|
-
.set('Accept-Encoding', 'gzip');
|
|
108
|
-
s.close();
|
|
109
|
-
expect(res.headers['content-encoding']).toBe('gzip');
|
|
110
|
-
// supertest auto-decompresses gzip
|
|
111
|
-
expect(res.text).toBe('tiny');
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// āāā compression: false shorthand āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
116
|
-
|
|
117
|
-
describe('Compression ā disabled', () => {
|
|
118
|
-
let server;
|
|
119
|
-
beforeAll(() => { server = createApp({ compression: false }); });
|
|
120
|
-
afterAll(() => server.close());
|
|
121
|
-
|
|
122
|
-
test('compression: false ā no compression on any file', async () => {
|
|
123
|
-
const res = await supertest(server)
|
|
124
|
-
.get('/large.txt')
|
|
125
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
126
|
-
expect(res.status).toBe(200);
|
|
127
|
-
expect(res.headers['content-encoding']).toBeUndefined();
|
|
128
|
-
expect(res.text).toBe('A'.repeat(2000));
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// āāā encodings configuration āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
133
|
-
|
|
134
|
-
describe('Compression ā encodings configuration', () => {
|
|
135
|
-
test('encodings: [gzip] ā no brotli even if client prefers br', async () => {
|
|
136
|
-
const s = createApp({ compression: { encodings: ['gzip'] } });
|
|
137
|
-
const res = await supertest(s)
|
|
138
|
-
.get('/large.txt')
|
|
139
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
140
|
-
s.close();
|
|
141
|
-
expect(res.headers['content-encoding']).toBe('gzip');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('encodings: [] ā no compression', async () => {
|
|
145
|
-
const s = createApp({ compression: { encodings: [] } });
|
|
146
|
-
const res = await supertest(s)
|
|
147
|
-
.get('/large.txt')
|
|
148
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
149
|
-
s.close();
|
|
150
|
-
expect(res.headers['content-encoding']).toBeUndefined();
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
// āāā mimeTypes configuration āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
155
|
-
|
|
156
|
-
describe('Compression ā mimeTypes configuration', () => {
|
|
157
|
-
test('custom mimeTypes replaces default list', async () => {
|
|
158
|
-
// Only compress application/json; text/plain should not be compressed
|
|
159
|
-
const s = createApp({ compression: { mimeTypes: ['application/json'], threshold: false } });
|
|
160
|
-
|
|
161
|
-
const resTxt = await supertest(s)
|
|
162
|
-
.get('/large.txt')
|
|
163
|
-
.set('Accept-Encoding', 'gzip');
|
|
164
|
-
expect(resTxt.headers['content-encoding']).toBeUndefined();
|
|
165
|
-
|
|
166
|
-
s.close();
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
// āāā ETag encoding-specific āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
171
|
-
|
|
172
|
-
describe('Compression ā encoding-specific ETag', () => {
|
|
173
|
-
let server;
|
|
174
|
-
beforeAll(() => { server = createApp({ browserCacheEnabled: true }); });
|
|
175
|
-
afterAll(() => server.close());
|
|
176
|
-
|
|
177
|
-
test('ETag for br response has -br suffix', async () => {
|
|
178
|
-
const res = await supertest(server)
|
|
179
|
-
.get('/large.txt')
|
|
180
|
-
.set('Accept-Encoding', 'br');
|
|
181
|
-
expect(res.headers['etag']).toMatch(/-br"$/);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
test('ETag for gzip response has -gz suffix', async () => {
|
|
185
|
-
const res = await supertest(server)
|
|
186
|
-
.get('/large.txt')
|
|
187
|
-
.set('Accept-Encoding', 'gzip');
|
|
188
|
-
expect(res.headers['etag']).toMatch(/-gz"$/);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
test('ETag for uncompressed response has no suffix', async () => {
|
|
192
|
-
// Use 'identity' to prevent supertest's default Accept-Encoding from triggering compression
|
|
193
|
-
const res = await supertest(server)
|
|
194
|
-
.get('/large.txt')
|
|
195
|
-
.set('Accept-Encoding', 'identity');
|
|
196
|
-
expect(res.headers['etag']).not.toMatch(/-(br|gz)"$/);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test('304 returned when If-None-Match matches encoding-specific ETag', async () => {
|
|
200
|
-
const first = await supertest(server)
|
|
201
|
-
.get('/large.txt')
|
|
202
|
-
.set('Accept-Encoding', 'gzip');
|
|
203
|
-
const etag = first.headers['etag'];
|
|
204
|
-
|
|
205
|
-
const second = await supertest(server)
|
|
206
|
-
.get('/large.txt')
|
|
207
|
-
.set('Accept-Encoding', 'gzip')
|
|
208
|
-
.set('If-None-Match', etag);
|
|
209
|
-
expect(second.status).toBe(304);
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
test('304 NOT returned when ETag suffix differs (br ETag sent with gzip request)', async () => {
|
|
213
|
-
const brRes = await supertest(server)
|
|
214
|
-
.get('/large.txt')
|
|
215
|
-
.set('Accept-Encoding', 'br');
|
|
216
|
-
const brEtag = brRes.headers['etag'];
|
|
217
|
-
|
|
218
|
-
// Send the br ETag but request gzip ā ETag mismatch ā 200
|
|
219
|
-
const gzipRes = await supertest(server)
|
|
220
|
-
.get('/large.txt')
|
|
221
|
-
.set('Accept-Encoding', 'gzip')
|
|
222
|
-
.set('If-None-Match', brEtag);
|
|
223
|
-
expect(gzipRes.status).toBe(200);
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
// āāā serverCache.compressedFile disabled (streaming mode) āāāāāāāāāāāāāāāāāāāā
|
|
228
|
-
|
|
229
|
-
describe('Compression ā serverCache.compressedFile disabled (streaming)', () => {
|
|
230
|
-
let server;
|
|
231
|
-
beforeAll(() => {
|
|
232
|
-
server = createApp({ serverCache: { compressedFile: { enabled: false } } });
|
|
233
|
-
});
|
|
234
|
-
afterAll(() => server.close());
|
|
235
|
-
|
|
236
|
-
test('streaming: Content-Encoding set but no Content-Length', async () => {
|
|
237
|
-
const res = await supertest(server)
|
|
238
|
-
.get('/large.txt')
|
|
239
|
-
.set('Accept-Encoding', 'gzip');
|
|
240
|
-
expect(res.headers['content-encoding']).toBe('gzip');
|
|
241
|
-
// Streaming compressed responses use Transfer-Encoding: chunked ā no Content-Length
|
|
242
|
-
expect(res.headers['content-length']).toBeUndefined();
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test('streaming: response body is correctly decompressed', async () => {
|
|
246
|
-
const res = await supertest(server)
|
|
247
|
-
.get('/large.txt')
|
|
248
|
-
.set('Accept-Encoding', 'gzip');
|
|
249
|
-
// supertest auto-decompresses gzip ā res.text is the original content
|
|
250
|
-
expect(res.text).toBe('A'.repeat(2000));
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
// āāā Compression does not apply to Range requests āāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
255
|
-
|
|
256
|
-
describe('Compression ā no compression on Range requests (HTTP 206)', () => {
|
|
257
|
-
let server;
|
|
258
|
-
beforeAll(() => { server = createApp(); });
|
|
259
|
-
afterAll(() => server.close());
|
|
260
|
-
|
|
261
|
-
test('Range request is served uncompressed even with Accept-Encoding', async () => {
|
|
262
|
-
const res = await supertest(server)
|
|
263
|
-
.get('/large.txt')
|
|
264
|
-
.set('Range', 'bytes=0-9')
|
|
265
|
-
.set('Accept-Encoding', 'br, gzip');
|
|
266
|
-
expect(res.status).toBe(206);
|
|
267
|
-
expect(res.headers['content-encoding']).toBeUndefined();
|
|
268
|
-
expect(res.text).toBe('A'.repeat(10));
|
|
269
|
-
});
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// āāā V3 migration guard āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
273
|
-
|
|
274
|
-
describe('Compression ā V3 migration guard (old name throws helpful error)', () => {
|
|
275
|
-
test('compression.minSize throws with hint pointing to minFileSize', () => {
|
|
276
|
-
expect(() => koaClassicServer(root, { compression: { minSize: 2048 } }))
|
|
277
|
-
.toThrow(/options\.compression\.minSize was renamed[\s\S]*compression: \{ minFileSize: 2048 \}/);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test('compression.minSize === false also throws (legacy "no minimum" sentinel)', () => {
|
|
281
|
-
expect(() => koaClassicServer(root, { compression: { minSize: false } }))
|
|
282
|
-
.toThrow(/options\.compression\.minSize was renamed/);
|
|
283
|
-
});
|
|
284
|
-
});
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
## questi ile servono per testare manualmente le vari conigurazioni
|
|
2
|
-
|
|
3
|
-
# digitando :
|
|
4
|
-
### npm run loadConfig
|
|
5
|
-
# potrai sceglire quale configurazione usare per caricare il server e testatarlo la directory puntata ĆØ la stessa contenuta nella directory __tests__
|
|
6
|
-
# cioĆØ __tests__/publicWwwTest
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// questo script permetterĆ di scegliere la conigurazione con cui lanciare koa-classic-server al ine di essere testato
|
|
2
|
-
// ci sarĆ una lista interattive di configurazione fra cui scegliere :
|
|
3
|
-
|
|
4
|
-
// chooseCon.js
|
|
5
|
-
const { createServer, configurations } = require('../customTest/serversToLoad.util');
|
|
6
|
-
const inquirer = require('inquirer').default;
|
|
7
|
-
|
|
8
|
-
async function chooseConfiguration() {
|
|
9
|
-
// Costruiamo le scelte dall'array delle configurazioni
|
|
10
|
-
const choices = configurations.map(config => ({
|
|
11
|
-
name: `${config.name}: ${config.description}`,
|
|
12
|
-
value: config.name,
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
const answers = await inquirer.prompt([
|
|
16
|
-
{
|
|
17
|
-
type: 'list',
|
|
18
|
-
name: 'configName',
|
|
19
|
-
message: 'Seleziona la configurazione da visualizzare:',
|
|
20
|
-
choices: choices,
|
|
21
|
-
},
|
|
22
|
-
]);
|
|
23
|
-
|
|
24
|
-
return answers.configName;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function main() {
|
|
28
|
-
const configName = await chooseConfiguration();
|
|
29
|
-
const app = createServer(configName);
|
|
30
|
-
const port = process.env.PORT || 3000;
|
|
31
|
-
|
|
32
|
-
app.listen(port, () => {
|
|
33
|
-
console.log(`Server avviato su http://localhost:${port} con configurazione "${configName}"`);
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
main().catch(error => {
|
|
38
|
-
console.error('Errore durante l\'esecuzione:', error);
|
|
39
|
-
process.exit(1);
|
|
40
|
-
});
|
|
41
|
-
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// quivi sarnno elencato in un array le varie possibili configurzioni di koaClassicServer in modo po sa poterle testare
|
|
2
|
-
|
|
3
|
-
// servers.js
|
|
4
|
-
const Koa = require('koa');
|
|
5
|
-
const koaClassicServer = require('../index.cjs');
|
|
6
|
-
const { join } = require('path');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Array (o raccolta) delle configurazioni disponibili.
|
|
10
|
-
* Aggiungendo nuovi oggetti qui potrai testare ulteriori configurazioni.
|
|
11
|
-
*/
|
|
12
|
-
rootDir = join(__dirname, '../' , '__tests__','publicWwwTest');
|
|
13
|
-
console.log( 'rootDir', rootDir);
|
|
14
|
-
const configurations = [
|
|
15
|
-
{
|
|
16
|
-
name: 'test generico',
|
|
17
|
-
description: ' urlPrefix: \',',
|
|
18
|
-
// Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
|
|
19
|
-
rootDir: rootDir,
|
|
20
|
-
options: {
|
|
21
|
-
//urlPrefix: '/',
|
|
22
|
-
method: ['GET'],
|
|
23
|
-
dirListing: { enabled: true },
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: 'test indicando l\'index file ',
|
|
28
|
-
description: "nelle urlPrefix: \'/public\', : //index: 'index.html',",
|
|
29
|
-
// In produzione potresti servire i file dalla cartella "public"
|
|
30
|
-
rootDir: rootDir,
|
|
31
|
-
options: {
|
|
32
|
-
urlPrefix: '/public',
|
|
33
|
-
method: ['GET'],
|
|
34
|
-
dirListing: { enabled: true },
|
|
35
|
-
index: ['index.html'],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
name: 'test generico',
|
|
40
|
-
description: ' urlPrefix: \'/public\',',
|
|
41
|
-
// Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
|
|
42
|
-
rootDir: rootDir,
|
|
43
|
-
options: {
|
|
44
|
-
urlPrefix: '/public',
|
|
45
|
-
method: ['GET'],
|
|
46
|
-
dirListing: { enabled: true },
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
name: 'test con percorso riservato ',
|
|
51
|
-
description: "urlsReserved : Array('percorso_riservato/', 'percorso riservato con spazi')",
|
|
52
|
-
// Per i test, i file da servire sono quelli della cartella __tests__/publicWwwTest
|
|
53
|
-
rootDir: rootDir,
|
|
54
|
-
options: {
|
|
55
|
-
urlPrefix: '',
|
|
56
|
-
method: ['GET'],
|
|
57
|
-
dirListing: { enabled: true },
|
|
58
|
-
urlsReserved : Array('/percorso_riservato', '/percorso riservato con spazi')
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
// Puoi aggiungere ulteriori configurazioni qui
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Cerca e restituisce la configurazione in base al nome.
|
|
66
|
-
* Se non viene trovata, restituisce la prima (default).
|
|
67
|
-
*
|
|
68
|
-
* @param {string} configName - Il nome della configurazione da usare.
|
|
69
|
-
* @returns {object} La configurazione trovata.
|
|
70
|
-
*/
|
|
71
|
-
function getConfig(configName) {
|
|
72
|
-
return configurations.find(config => config.name === configName) || configurations[0];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Crea un'istanza di Koa configurata in base alla configurazione scelta.
|
|
77
|
-
*
|
|
78
|
-
* @param {string} configName - Il nome della configurazione da utilizzare (default: 'default').
|
|
79
|
-
* @returns {Koa} L'istanza dell'applicazione Koa.
|
|
80
|
-
*/
|
|
81
|
-
function createServer( configName ) {
|
|
82
|
-
const config = getConfig(configName);
|
|
83
|
-
const app = new Koa();
|
|
84
|
-
console.log('config.options', config.options, 'config.rootDir' , config.rootDir);
|
|
85
|
-
app.use(koaClassicServer(config.rootDir, config.options));
|
|
86
|
-
return app;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
module.exports = {
|
|
90
|
-
configurations,
|
|
91
|
-
getConfig,
|
|
92
|
-
createServer,
|
|
93
|
-
};
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Demo: Enhanced index option with RegExp support
|
|
5
|
-
*
|
|
6
|
-
* Questo esempio dimostra come usare RegExp nell'opzione index
|
|
7
|
-
* per matching case-insensitive e pattern flessibili
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const Koa = require('koa');
|
|
11
|
-
const koaClassicServer = require('./index.cjs');
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
// Crea directory di test
|
|
16
|
-
const testDir = path.join(__dirname, 'demo-regex-test');
|
|
17
|
-
if (!fs.existsSync(testDir)) {
|
|
18
|
-
fs.mkdirSync(testDir);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Crea file di test con vari case
|
|
22
|
-
console.log('š Creazione file di test...\n');
|
|
23
|
-
|
|
24
|
-
const files = [
|
|
25
|
-
{ name: 'INDEX.HTML', content: '<h1 style="color: red;">Trovato INDEX.HTML (maiuscolo)</h1>' },
|
|
26
|
-
{ name: 'Index.Html', content: '<h1 style="color: blue;">Trovato Index.Html (mixed case)</h1>' },
|
|
27
|
-
{ name: 'index.htm', content: '<h1 style="color: green;">Trovato index.htm (estensione .htm)</h1>' },
|
|
28
|
-
{ name: 'default.html', content: '<h1 style="color: orange;">Trovato default.html</h1>' },
|
|
29
|
-
{ name: 'readme.txt', content: 'Questo ĆØ un file normale' }
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
files.forEach(file => {
|
|
33
|
-
const filePath = path.join(testDir, file.name);
|
|
34
|
-
fs.writeFileSync(filePath, file.content);
|
|
35
|
-
console.log(` ā Creato: ${file.name}`);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
console.log('\n' + '='.repeat(70));
|
|
39
|
-
console.log('š§Ŗ TEST CONFIGURAZIONI DIVERSE\n');
|
|
40
|
-
|
|
41
|
-
// ============================================================================
|
|
42
|
-
// TEST 1: Solo case-insensitive .html
|
|
43
|
-
// ============================================================================
|
|
44
|
-
console.log('TEST 1: RegExp case-insensitive /index\\.html/i');
|
|
45
|
-
console.log(' Pattern: [/index\\.html/i]');
|
|
46
|
-
console.log(' Aspettativa: Matcha INDEX.HTML o Index.Html');
|
|
47
|
-
|
|
48
|
-
const app1 = new Koa();
|
|
49
|
-
app1.use(koaClassicServer(testDir, {
|
|
50
|
-
index: [/index\.html/i],
|
|
51
|
-
dirListing: { enabled: true }
|
|
52
|
-
}));
|
|
53
|
-
const server1 = app1.listen(3001);
|
|
54
|
-
console.log(' ā Server avviato su http://localhost:3001\n');
|
|
55
|
-
|
|
56
|
-
// ============================================================================
|
|
57
|
-
// TEST 2: Multiple estensioni (.html e .htm)
|
|
58
|
-
// ============================================================================
|
|
59
|
-
console.log('TEST 2: RegExp per .html e .htm');
|
|
60
|
-
console.log(' Pattern: [/index\\.(html|htm)/i]');
|
|
61
|
-
console.log(' Aspettativa: Matcha INDEX.HTML, Index.Html, index.htm');
|
|
62
|
-
|
|
63
|
-
const app2 = new Koa();
|
|
64
|
-
app2.use(koaClassicServer(testDir, {
|
|
65
|
-
index: [/index\.(html|htm)/i],
|
|
66
|
-
dirListing: { enabled: true }
|
|
67
|
-
}));
|
|
68
|
-
const server2 = app2.listen(3002);
|
|
69
|
-
console.log(' ā Server avviato su http://localhost:3002\n');
|
|
70
|
-
|
|
71
|
-
// ============================================================================
|
|
72
|
-
// TEST 3: Priority: index.html prima, poi default.html
|
|
73
|
-
// ============================================================================
|
|
74
|
-
console.log('TEST 3: Array con prioritĆ ');
|
|
75
|
-
console.log(' Pattern: [/index\\.(html|htm)/i, /default\\.html/i]');
|
|
76
|
-
console.log(' Aspettativa: Prima cerca index.*, poi default.html');
|
|
77
|
-
|
|
78
|
-
const app3 = new Koa();
|
|
79
|
-
app3.use(koaClassicServer(testDir, {
|
|
80
|
-
index: [
|
|
81
|
-
/index\.(html|htm)/i,
|
|
82
|
-
/default\.html/i
|
|
83
|
-
],
|
|
84
|
-
dirListing: { enabled: true }
|
|
85
|
-
}));
|
|
86
|
-
const server3 = app3.listen(3003);
|
|
87
|
-
console.log(' ā Server avviato su http://localhost:3003\n');
|
|
88
|
-
|
|
89
|
-
// ============================================================================
|
|
90
|
-
// TEST 4: Mixed (string + RegExp)
|
|
91
|
-
// ============================================================================
|
|
92
|
-
console.log('TEST 4: Mixed array (string exact + RegExp fallback)');
|
|
93
|
-
console.log(' Pattern: ["index.html", /INDEX\\.HTML/i, /default\\.html/i]');
|
|
94
|
-
console.log(' Aspettativa: Prima exact "index.html", poi case-insensitive');
|
|
95
|
-
|
|
96
|
-
const app4 = new Koa();
|
|
97
|
-
app4.use(koaClassicServer(testDir, {
|
|
98
|
-
index: [
|
|
99
|
-
'index.html', // Exact match (più veloce)
|
|
100
|
-
/INDEX\.HTML/i, // Case-insensitive fallback
|
|
101
|
-
/default\.html/i // Default fallback
|
|
102
|
-
],
|
|
103
|
-
dirListing: { enabled: true }
|
|
104
|
-
}));
|
|
105
|
-
const server4 = app4.listen(3004);
|
|
106
|
-
console.log(' ā Server avviato su http://localhost:3004\n');
|
|
107
|
-
|
|
108
|
-
console.log('='.repeat(70));
|
|
109
|
-
console.log('\nš SERVER ATTIVI:\n');
|
|
110
|
-
console.log(' 1ļøā£ http://localhost:3001 - Case-insensitive /index\\.html/i');
|
|
111
|
-
console.log(' 2ļøā£ http://localhost:3002 - Multi-extension /index\\.(html|htm)/i');
|
|
112
|
-
console.log(' 3ļøā£ http://localhost:3003 - Priority array con fallback');
|
|
113
|
-
console.log(' 4ļøā£ http://localhost:3004 - Mixed string + RegExp\n');
|
|
114
|
-
|
|
115
|
-
console.log('š File presenti nella directory:');
|
|
116
|
-
files.forEach(file => {
|
|
117
|
-
console.log(` - ${file.name}`);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
console.log('\nš” Prova ad aprire i link sopra per vedere quale file viene servito!');
|
|
121
|
-
console.log(' Ogni server ha una configurazione diversa.\n');
|
|
122
|
-
console.log('ā¹ļø Premi Ctrl+C per fermare i server\n');
|
|
123
|
-
|
|
124
|
-
// Cleanup on exit
|
|
125
|
-
process.on('SIGINT', () => {
|
|
126
|
-
console.log('\n\nš§¹ Chiusura server e pulizia...');
|
|
127
|
-
server1.close();
|
|
128
|
-
server2.close();
|
|
129
|
-
server3.close();
|
|
130
|
-
server4.close();
|
|
131
|
-
|
|
132
|
-
// Rimuovi file di test
|
|
133
|
-
files.forEach(file => {
|
|
134
|
-
fs.unlinkSync(path.join(testDir, file.name));
|
|
135
|
-
});
|
|
136
|
-
fs.rmdirSync(testDir);
|
|
137
|
-
|
|
138
|
-
console.log('ā Cleanup completato\n');
|
|
139
|
-
process.exit(0);
|
|
140
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2
|
-
//
|
|
3
|
-
// TEST FOR REMOVED OPTION NAMES (enableCaching, cacheMaxAge)
|
|
4
|
-
// These options were removed in v3.0.0 ā passing them must throw an Error.
|
|
5
|
-
//
|
|
6
|
-
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
7
|
-
|
|
8
|
-
const koaClassicServer = require('../index.cjs');
|
|
9
|
-
const Koa = require('koa');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
const rootDir = path.join(__dirname, 'publicWwwTest');
|
|
13
|
-
|
|
14
|
-
describe('Removed option names (v3.0.0 breaking changes)', () => {
|
|
15
|
-
|
|
16
|
-
test('should throw when "enableCaching" is passed', () => {
|
|
17
|
-
expect(() => {
|
|
18
|
-
const app = new Koa();
|
|
19
|
-
app.use(koaClassicServer(rootDir, { enableCaching: true }));
|
|
20
|
-
}).toThrow('"enableCaching" option was removed in v3.0.0');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('should throw when "cacheMaxAge" is passed', () => {
|
|
24
|
-
expect(() => {
|
|
25
|
-
const app = new Koa();
|
|
26
|
-
app.use(koaClassicServer(rootDir, { cacheMaxAge: 3600 }));
|
|
27
|
-
}).toThrow('"cacheMaxAge" option was removed in v3.0.0');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('should throw even when new option is also provided alongside "cacheMaxAge"', () => {
|
|
31
|
-
expect(() => {
|
|
32
|
-
const app = new Koa();
|
|
33
|
-
app.use(koaClassicServer(rootDir, { cacheMaxAge: 3600, browserCacheMaxAge: 3600 }));
|
|
34
|
-
}).toThrow('"cacheMaxAge" option was removed in v3.0.0');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('should throw even when new option is also provided alongside "enableCaching"', () => {
|
|
38
|
-
expect(() => {
|
|
39
|
-
const app = new Koa();
|
|
40
|
-
app.use(koaClassicServer(rootDir, { enableCaching: false, browserCacheEnabled: false }));
|
|
41
|
-
}).toThrow('"enableCaching" option was removed in v3.0.0');
|
|
42
|
-
});
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
describe('New option names (browserCacheEnabled / browserCacheMaxAge)', () => {
|
|
46
|
-
const supertest = require('supertest');
|
|
47
|
-
let app;
|
|
48
|
-
let server;
|
|
49
|
-
let consoleWarnSpy;
|
|
50
|
-
|
|
51
|
-
beforeAll(() => {
|
|
52
|
-
consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
53
|
-
|
|
54
|
-
app = new Koa();
|
|
55
|
-
app.use(koaClassicServer(rootDir, {
|
|
56
|
-
browserCacheEnabled: true,
|
|
57
|
-
browserCacheMaxAge: 3600
|
|
58
|
-
}));
|
|
59
|
-
|
|
60
|
-
server = app.listen();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
afterAll(() => {
|
|
64
|
-
server.close();
|
|
65
|
-
consoleWarnSpy.mockRestore();
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test('should not warn about removed options', () => {
|
|
69
|
-
const removedWarnings = consoleWarnSpy.mock.calls.filter(call =>
|
|
70
|
-
call[1] && (call[1].includes('enableCaching') || call[1].includes('cacheMaxAge'))
|
|
71
|
-
);
|
|
72
|
-
expect(removedWarnings.length).toBe(0);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test('should work correctly with new option names', async () => {
|
|
76
|
-
const response = await supertest(server).get('/test-page.html');
|
|
77
|
-
|
|
78
|
-
expect(response.status).toBe(200);
|
|
79
|
-
expect(response.headers['etag']).toBeDefined();
|
|
80
|
-
expect(response.headers['cache-control']).toContain('max-age=3600');
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
describe('Default behavior (no caching options specified)', () => {
|
|
85
|
-
const supertest = require('supertest');
|
|
86
|
-
let app;
|
|
87
|
-
let server;
|
|
88
|
-
|
|
89
|
-
beforeAll(() => {
|
|
90
|
-
app = new Koa();
|
|
91
|
-
app.use(koaClassicServer(rootDir));
|
|
92
|
-
server = app.listen();
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
afterAll(() => {
|
|
96
|
-
server.close();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('should default to browserCacheEnabled: false', async () => {
|
|
100
|
-
const response = await supertest(server).get('/test-page.html');
|
|
101
|
-
|
|
102
|
-
expect(response.status).toBe(200);
|
|
103
|
-
expect(response.headers['cache-control']).toContain('no-cache');
|
|
104
|
-
});
|
|
105
|
-
});
|