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,527 @@
|
|
|
1
|
+
# Index Option - Comportamento di Priorità
|
|
2
|
+
|
|
3
|
+
## ⚠️ Formato Raccomandato: Array
|
|
4
|
+
|
|
5
|
+
**L'opzione `index` deve essere usata in formato array.**
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
// ✅ RACCOMANDATO (Array format)
|
|
9
|
+
index: ['index.html']
|
|
10
|
+
index: ['index.html', 'index.htm', 'default.html']
|
|
11
|
+
index: [/index\.html/i]
|
|
12
|
+
|
|
13
|
+
// ⚠️ DEPRECATO (String format - verrà rimosso in futuro)
|
|
14
|
+
index: 'index.html' // Genera un warning, usa ['index.html'] invece
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Nota importante:** Il formato stringa (`index: 'index.html'`) è **deprecato** e verrà rimosso in versioni future. Quando viene usato, viene mostrato un warning in console:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
[koa-classic-server] DEPRECATION WARNING: Passing a string to the "index" option is deprecated...
|
|
21
|
+
Current usage: index: "index.html"
|
|
22
|
+
Recommended: index: ["index.html"]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Principio Fondamentale: "First Match Wins"
|
|
28
|
+
|
|
29
|
+
L'opzione `index` utilizza il principio **"first match wins"** (primo match vince): l'array viene cercato **esattamente nell'ordine** specificato, e il **primo file trovato** viene servito.
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
index: [pattern1, pattern2, pattern3, ...]
|
|
33
|
+
↑ ↑ ↑
|
|
34
|
+
PRIMO SECONDO TERZO
|
|
35
|
+
(priorità (priorità (priorità
|
|
36
|
+
massima) media) bassa)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Comportamento di Ricerca
|
|
42
|
+
|
|
43
|
+
### 1. Ordine di Ricerca Sequenziale
|
|
44
|
+
|
|
45
|
+
L'algoritmo cerca i file nell'ordine esatto dell'array: `[0] → [1] → [2] → [3] → ...`
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Passi eseguiti:**
|
|
52
|
+
1. Cerca `index1.html` nella directory
|
|
53
|
+
- ✅ Se trovato → **SERVE index1.html** (STOP, ignora index2 e index3)
|
|
54
|
+
- ❌ Se non trovato → Passa al passo 2
|
|
55
|
+
|
|
56
|
+
2. Cerca `index2.html` nella directory
|
|
57
|
+
- ✅ Se trovato → **SERVE index2.html** (STOP, ignora index3)
|
|
58
|
+
- ❌ Se non trovato → Passa al passo 3
|
|
59
|
+
|
|
60
|
+
3. Cerca `index3.html` nella directory
|
|
61
|
+
- ✅ Se trovato → **SERVE index3.html** (STOP)
|
|
62
|
+
- ❌ Se non trovato → Passa al passo 4
|
|
63
|
+
|
|
64
|
+
4. Nessun file trovato → **Mostra directory listing** (se `showDirContents: true`)
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Comportamento con String
|
|
69
|
+
|
|
70
|
+
### Esempio 1: Tutti i file presenti
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
// Directory contiene:
|
|
74
|
+
// - index1.html
|
|
75
|
+
// - index2.html
|
|
76
|
+
// - index3.html
|
|
77
|
+
|
|
78
|
+
app.use(koaClassicServer('./public', {
|
|
79
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
// Risultato: Serve index1.html ✅
|
|
83
|
+
// Motivo: È il primo nell'array
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Esempio 2: Primo file mancante
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// Directory contiene:
|
|
90
|
+
// - index2.html (index1.html NON esiste!)
|
|
91
|
+
// - index3.html
|
|
92
|
+
|
|
93
|
+
app.use(koaClassicServer('./public', {
|
|
94
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
95
|
+
}));
|
|
96
|
+
|
|
97
|
+
// Risultato: Serve index2.html ✅
|
|
98
|
+
// Motivo: index1.html non esiste, index2.html è il primo disponibile
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Esempio 3: Solo l'ultimo file presente
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
// Directory contiene:
|
|
105
|
+
// - index3.html (index1.html e index2.html NON esistono!)
|
|
106
|
+
|
|
107
|
+
app.use(koaClassicServer('./public', {
|
|
108
|
+
index: ['index1.html', 'index2.html', 'index3.html']
|
|
109
|
+
}));
|
|
110
|
+
|
|
111
|
+
// Risultato: Serve index3.html ✅
|
|
112
|
+
// Motivo: È l'unico disponibile nell'array
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Comportamento con RegExp
|
|
118
|
+
|
|
119
|
+
**LA PRIORITÀ FUNZIONA ALLO STESSO MODO CON LE REGEXP!**
|
|
120
|
+
|
|
121
|
+
### Esempio 1: Tutte le RegExp matchano
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// Directory contiene:
|
|
125
|
+
// - index1.html
|
|
126
|
+
// - index2.html
|
|
127
|
+
// - index3.html
|
|
128
|
+
|
|
129
|
+
app.use(koaClassicServer('./public', {
|
|
130
|
+
index: [
|
|
131
|
+
/index1\.html/i, // ← PRIMO pattern
|
|
132
|
+
/index2\.html/i, // ← SECONDO pattern
|
|
133
|
+
/index3\.html/i // ← TERZO pattern
|
|
134
|
+
]
|
|
135
|
+
}));
|
|
136
|
+
|
|
137
|
+
// Risultato: Serve index1.html ✅
|
|
138
|
+
// Motivo: Il primo pattern /index1\.html/i matcha index1.html
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Esempio 2: Primo pattern non matcha
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
// Directory contiene:
|
|
145
|
+
// - index2.html (index1.html NON esiste!)
|
|
146
|
+
// - index3.html
|
|
147
|
+
|
|
148
|
+
app.use(koaClassicServer('./public', {
|
|
149
|
+
index: [
|
|
150
|
+
/index1\.html/i, // ← PRIMO pattern (non matcha nulla)
|
|
151
|
+
/index2\.html/i, // ← SECONDO pattern (matcha!)
|
|
152
|
+
/index3\.html/i // ← TERZO pattern
|
|
153
|
+
]
|
|
154
|
+
}));
|
|
155
|
+
|
|
156
|
+
// Risultato: Serve index2.html ✅
|
|
157
|
+
// Motivo: Primo pattern non matcha, secondo pattern matcha index2.html
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Esempio 3: Pattern largo prima di pattern stretto
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
// Directory contiene:
|
|
164
|
+
// - index.html
|
|
165
|
+
// - index.htm
|
|
166
|
+
// - default.html
|
|
167
|
+
|
|
168
|
+
app.use(koaClassicServer('./public', {
|
|
169
|
+
index: [
|
|
170
|
+
/index\.(html|htm)/i, // ← Pattern LARGO (matcha .html E .htm)
|
|
171
|
+
/default\.html/i // ← Pattern STRETTO (mai raggiunto!)
|
|
172
|
+
]
|
|
173
|
+
}));
|
|
174
|
+
|
|
175
|
+
// Risultato: Serve index.html O index.htm ✅
|
|
176
|
+
// Motivo: Primo pattern matcha, secondo pattern viene ignorato
|
|
177
|
+
// ⚠️ ATTENZIONE: default.html NON verrà MAI servito!
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Comportamento con Mixed Array (String + RegExp)
|
|
183
|
+
|
|
184
|
+
Stesso principio: l'ordine dell'array determina la priorità, **indipendentemente dal tipo**.
|
|
185
|
+
|
|
186
|
+
### Esempio 1: String prima di RegExp
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
// Directory contiene:
|
|
190
|
+
// - index.html
|
|
191
|
+
// - INDEX.HTML (case diverso!)
|
|
192
|
+
|
|
193
|
+
app.use(koaClassicServer('./public', {
|
|
194
|
+
index: [
|
|
195
|
+
'index.html', // ← String (case-sensitive, exact match)
|
|
196
|
+
/INDEX\.HTML/i // ← RegExp (case-insensitive)
|
|
197
|
+
]
|
|
198
|
+
}));
|
|
199
|
+
|
|
200
|
+
// Risultato: Serve index.html ✅ (se esiste)
|
|
201
|
+
// Se index.html non esiste → Serve INDEX.HTML ✅
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Esempio 2: RegExp prima di String
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// Directory contiene:
|
|
208
|
+
// - INDEX.HTML (maiuscolo)
|
|
209
|
+
// - index.html (minuscolo)
|
|
210
|
+
|
|
211
|
+
app.use(koaClassicServer('./public', {
|
|
212
|
+
index: [
|
|
213
|
+
/index\.html/i, // ← RegExp (case-insensitive, primo!)
|
|
214
|
+
'index.html' // ← String (esatto, secondo)
|
|
215
|
+
]
|
|
216
|
+
}));
|
|
217
|
+
|
|
218
|
+
// Risultato: Serve INDEX.HTML o index.html ✅
|
|
219
|
+
// (dipende da quale il filesystem restituisce per primo)
|
|
220
|
+
// La stringa 'index.html' potrebbe non essere mai raggiunta!
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Pattern Matching e Filesystem Order
|
|
226
|
+
|
|
227
|
+
⚠️ **IMPORTANTE:** Quando una RegExp matcha **multipli file**, viene servito il **primo file trovato nell'ordine del filesystem**, che NON è garantito essere deterministico.
|
|
228
|
+
|
|
229
|
+
### Esempio: RegExp matcha multipli file
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
// Directory contiene:
|
|
233
|
+
// - INDEX.HTML
|
|
234
|
+
// - Index.Html
|
|
235
|
+
// - index.html
|
|
236
|
+
|
|
237
|
+
app.use(koaClassicServer('./public', {
|
|
238
|
+
index: [/index\.html/i] // Matcha tutti e 3 i file!
|
|
239
|
+
}));
|
|
240
|
+
|
|
241
|
+
// Risultato: Uno dei tre file (ordine NON garantito) ⚠️
|
|
242
|
+
// Soluzione: Usa stringhe esatte per controllo deterministico
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Soluzione Deterministica
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
// Per controllo esatto dell'ordine, usa stringhe:
|
|
249
|
+
app.use(koaClassicServer('./public', {
|
|
250
|
+
index: [
|
|
251
|
+
'index.html', // 1. Cerca esattamente questo
|
|
252
|
+
'Index.Html', // 2. Poi questo
|
|
253
|
+
'INDEX.HTML', // 3. Infine questo
|
|
254
|
+
/index\.html/i // 4. Fallback per altri casi
|
|
255
|
+
]
|
|
256
|
+
}));
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Best Practices
|
|
262
|
+
|
|
263
|
+
### ✅ Raccomandazione 1: Specifico prima, generico dopo
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// ✓ CORRETTO
|
|
267
|
+
index: [
|
|
268
|
+
'index.html', // Specifico: exact match (veloce)
|
|
269
|
+
/INDEX\.HTML/i, // Meno specifico: case-insensitive
|
|
270
|
+
/index\.(html|htm)/i, // Generico: multiple estensioni
|
|
271
|
+
/default\.html/i // Fallback: file alternativo
|
|
272
|
+
]
|
|
273
|
+
|
|
274
|
+
// ✗ SBAGLIATO
|
|
275
|
+
index: [
|
|
276
|
+
/index\.(html|htm)/i, // Troppo generico per primo!
|
|
277
|
+
'index.html' // Mai raggiunto se .htm esiste!
|
|
278
|
+
]
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### ✅ Raccomandazione 2: Performance - String prima di RegExp
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
// ✓ OTTIMIZZATO (String = O(1), RegExp = O(n))
|
|
285
|
+
index: [
|
|
286
|
+
'index.html', // O(1) lookup
|
|
287
|
+
'index.htm', // O(1) lookup
|
|
288
|
+
/INDEX\.HTML/i, // O(n) regex match
|
|
289
|
+
/default\.html/i // O(n) regex match
|
|
290
|
+
]
|
|
291
|
+
|
|
292
|
+
// ✗ LENTO
|
|
293
|
+
index: [
|
|
294
|
+
/index\.html/i, // O(n) regex match per primo
|
|
295
|
+
/index\.htm/i, // O(n) regex match
|
|
296
|
+
'index.html' // O(1) ma mai raggiunto!
|
|
297
|
+
]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### ✅ Raccomandazione 3: Evita pattern troppo ampi all'inizio
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
// ✗ PROBLEMATICO
|
|
304
|
+
index: [
|
|
305
|
+
/.*\.html/i, // Matcha QUALSIASI .html (troppo largo!)
|
|
306
|
+
'index.html' // Mai raggiunto!
|
|
307
|
+
]
|
|
308
|
+
|
|
309
|
+
// ✓ CORRETTO
|
|
310
|
+
index: [
|
|
311
|
+
'index.html', // Prima cerca file specifico
|
|
312
|
+
/^index\./i, // Poi file che iniziano con "index."
|
|
313
|
+
/.*\.html/i // Solo come ultimo fallback
|
|
314
|
+
]
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Diagramma di Flusso
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
┌─────────────────────────────┐
|
|
323
|
+
│ Richiesta GET / │
|
|
324
|
+
└──────────┬──────────────────┘
|
|
325
|
+
│
|
|
326
|
+
▼
|
|
327
|
+
┌─────────────────────────────┐
|
|
328
|
+
│ Leggi directory │
|
|
329
|
+
└──────────┬──────────────────┘
|
|
330
|
+
│
|
|
331
|
+
▼
|
|
332
|
+
┌─────────────────────────────┐
|
|
333
|
+
│ Pattern [0] (primo) │
|
|
334
|
+
└──────────┬──────────────────┘
|
|
335
|
+
│
|
|
336
|
+
▼
|
|
337
|
+
┌─────┴─────┐
|
|
338
|
+
│ Matcha? │
|
|
339
|
+
└─────┬─────┘
|
|
340
|
+
│
|
|
341
|
+
┌─────┴─────┐
|
|
342
|
+
│ │
|
|
343
|
+
SI NO
|
|
344
|
+
│ │
|
|
345
|
+
│ ▼
|
|
346
|
+
│ ┌───────────────┐
|
|
347
|
+
│ │ Pattern [1] │
|
|
348
|
+
│ └───────┬───────┘
|
|
349
|
+
│ │
|
|
350
|
+
│ ▼
|
|
351
|
+
│ ┌────┴────┐
|
|
352
|
+
│ │ Matcha? │
|
|
353
|
+
│ └────┬────┘
|
|
354
|
+
│ │
|
|
355
|
+
│ ┌────┴────┐
|
|
356
|
+
│ │ │
|
|
357
|
+
│ SI NO
|
|
358
|
+
│ │ │
|
|
359
|
+
│ │ ▼
|
|
360
|
+
│ │ ┌───────────┐
|
|
361
|
+
│ │ │Pattern [2]│
|
|
362
|
+
│ │ └─────┬─────┘
|
|
363
|
+
│ │ │
|
|
364
|
+
│ │ ...
|
|
365
|
+
│ │ │
|
|
366
|
+
│ │ ▼
|
|
367
|
+
│ │ ┌───────────────┐
|
|
368
|
+
│ │ │ Nessun match │
|
|
369
|
+
│ │ └───────┬───────┘
|
|
370
|
+
│ │ │
|
|
371
|
+
│ │ ▼
|
|
372
|
+
│ │ ┌────────────────┐
|
|
373
|
+
│ │ │ Directory │
|
|
374
|
+
│ │ │ listing │
|
|
375
|
+
│ │ └────────────────┘
|
|
376
|
+
│ │
|
|
377
|
+
▼ ▼
|
|
378
|
+
┌──────────────────┐
|
|
379
|
+
│ Serve il file │
|
|
380
|
+
│ STOP (ignora │
|
|
381
|
+
│ pattern restanti)│
|
|
382
|
+
└──────────────────┘
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Codice di Implementazione
|
|
388
|
+
|
|
389
|
+
Il comportamento di priorità è implementato nel file `index.cjs` alla funzione `findIndexFile()` (linee 205-250):
|
|
390
|
+
|
|
391
|
+
```javascript
|
|
392
|
+
// Search with priority order (first pattern wins)
|
|
393
|
+
for (const pattern of indexPatterns) {
|
|
394
|
+
let matchedFile = null;
|
|
395
|
+
|
|
396
|
+
if (typeof pattern === 'string') {
|
|
397
|
+
// Exact string match (case-sensitive)
|
|
398
|
+
if (fileNames.includes(pattern)) {
|
|
399
|
+
matchedFile = pattern;
|
|
400
|
+
}
|
|
401
|
+
} else if (pattern instanceof RegExp) {
|
|
402
|
+
// RegExp match (supports case-insensitive with /i flag)
|
|
403
|
+
matchedFile = fileNames.find(fileName => pattern.test(fileName));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// If match found, verify it's a file and return it
|
|
407
|
+
if (matchedFile) {
|
|
408
|
+
// ... verifica e return
|
|
409
|
+
return { name: matchedFile, stat: fileStat };
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// No match found
|
|
414
|
+
return null;
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**Punti chiave:**
|
|
418
|
+
- `for (const pattern of indexPatterns)` → Itera in ordine sequenziale
|
|
419
|
+
- `if (matchedFile) { return ... }` → **STOP al primo match**
|
|
420
|
+
- Pattern successivi vengono **ignorati completamente**
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Test Suite
|
|
425
|
+
|
|
426
|
+
Il comportamento di priorità è verificato da **24 test** in `__tests__/index-option.test.js`:
|
|
427
|
+
|
|
428
|
+
### Test con String:
|
|
429
|
+
- ✅ `Priority order - index1.html searched before index2.html`
|
|
430
|
+
- ✅ `Priority order - index2.html served when index1.html missing`
|
|
431
|
+
- ✅ `First match wins - index.html over index.htm`
|
|
432
|
+
- ✅ `First match wins - index.htm when index.html missing`
|
|
433
|
+
|
|
434
|
+
### Test con RegExp:
|
|
435
|
+
- ✅ `Priority order - First RegExp pattern searched before second`
|
|
436
|
+
- ✅ `Priority order - Second RegExp when first does not match`
|
|
437
|
+
- ✅ `Priority order - Broader pattern searched before narrower pattern`
|
|
438
|
+
|
|
439
|
+
### Test con Mixed Array:
|
|
440
|
+
- ✅ `Priority: String before RegExp`
|
|
441
|
+
- ✅ `Falls back to RegExp when string doesn't match`
|
|
442
|
+
- ✅ `Complex example: Mixed priorities`
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Esempi Reali
|
|
447
|
+
|
|
448
|
+
### Configurazione Apache-like
|
|
449
|
+
|
|
450
|
+
```javascript
|
|
451
|
+
app.use(koaClassicServer('./public', {
|
|
452
|
+
index: [
|
|
453
|
+
'index.html', // 1. Standard HTML
|
|
454
|
+
'index.htm', // 2. Legacy HTML
|
|
455
|
+
'index.php', // 3. PHP (se processato)
|
|
456
|
+
/index\.shtml/i, // 4. Server-side includes
|
|
457
|
+
'default.html' // 5. Fallback
|
|
458
|
+
]
|
|
459
|
+
}));
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Configurazione Template Engine
|
|
463
|
+
|
|
464
|
+
```javascript
|
|
465
|
+
app.use(koaClassicServer('./views', {
|
|
466
|
+
index: [
|
|
467
|
+
'index.ejs', // 1. EJS template (priorità)
|
|
468
|
+
'index.pug', // 2. Pug template
|
|
469
|
+
/index\.html/i, // 3. HTML statico
|
|
470
|
+
'index.htm' // 4. Legacy fallback
|
|
471
|
+
]
|
|
472
|
+
}));
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
### Configurazione Multilingua
|
|
476
|
+
|
|
477
|
+
```javascript
|
|
478
|
+
app.use(koaClassicServer('./public', {
|
|
479
|
+
index: [
|
|
480
|
+
'index_it.html', // 1. Italiano
|
|
481
|
+
'index_en.html', // 2. Inglese
|
|
482
|
+
/index_[a-z]{2}\.html/i, // 3. Altre lingue
|
|
483
|
+
'index.html' // 4. Default
|
|
484
|
+
]
|
|
485
|
+
}));
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## FAQ
|
|
491
|
+
|
|
492
|
+
### Q: L'ordine conta anche con le RegExp?
|
|
493
|
+
**A:** Sì! Le RegExp seguono **esattamente lo stesso comportamento** delle stringhe. Primo match vince, sempre.
|
|
494
|
+
|
|
495
|
+
### Q: Cosa succede se più file matchano la stessa RegExp?
|
|
496
|
+
**A:** Viene servito il primo file trovato nell'ordine del filesystem (non deterministico). Usa stringhe esatte per controllo preciso.
|
|
497
|
+
|
|
498
|
+
### Q: Posso mixare stringhe e RegExp?
|
|
499
|
+
**A:** Assolutamente sì! L'ordine dell'array determina la priorità, indipendentemente dal tipo.
|
|
500
|
+
|
|
501
|
+
### Q: Qual è più veloce: string o RegExp?
|
|
502
|
+
**A:** Le stringhe sono **molto più veloci** (O(1) vs O(n)). Metti sempre le stringhe prima delle RegExp.
|
|
503
|
+
|
|
504
|
+
### Q: Cosa succede se nessun pattern matcha?
|
|
505
|
+
**A:** Se `showDirContents: true`, mostra directory listing. Altrimenti restituisce 404.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## Riepilogo
|
|
510
|
+
|
|
511
|
+
| Aspetto | Comportamento |
|
|
512
|
+
|---------|--------------|
|
|
513
|
+
| **Ordine di ricerca** | Sequenziale: `[0] → [1] → [2] → ...` |
|
|
514
|
+
| **Quando si ferma** | Al **primo match** trovato |
|
|
515
|
+
| **String vs RegExp** | **Stesso comportamento** di priorità |
|
|
516
|
+
| **Mixed array** | Tipo **irrilevante**, conta solo l'ordine |
|
|
517
|
+
| **Performance** | String (O(1)) >> RegExp (O(n)) |
|
|
518
|
+
| **Deterministico** | String: sì, RegExp multipli: no |
|
|
519
|
+
| **Fallback** | Directory listing o 404 |
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
**Documentazione tecnica:** `index.cjs:28-48` (opzioni), `index.cjs:205-250` (implementazione)
|
|
524
|
+
|
|
525
|
+
**Test suite:** `__tests__/index-option.test.js` (24 test cases)
|
|
526
|
+
|
|
527
|
+
**Esempi pratici:** `EXAMPLES_INDEX_OPTION.md`
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 italopaesano
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|