koa-classic-server 2.0.0 → 2.1.2
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 +553 -127
- package/__tests__/directory-sorting-links.test.js +135 -0
- package/__tests__/ejs.test.js +299 -0
- package/__tests__/performance.test.js +75 -6
- package/__tests__/publicWwwTest/ejs-templates/complex.ejs +56 -0
- package/__tests__/publicWwwTest/ejs-templates/index.ejs +30 -0
- package/__tests__/publicWwwTest/ejs-templates/simple.ejs +13 -0
- package/__tests__/publicWwwTest/ejs-templates/with-conditional.ejs +28 -0
- package/__tests__/publicWwwTest/ejs-templates/with-escaping.ejs +26 -0
- package/__tests__/publicWwwTest/ejs-templates/with-loop.ejs +16 -0
- package/{scripts → __tests__}/setup-benchmark.js +1 -1
- package/docs/CODE_REVIEW.md +298 -0
- package/docs/FLOW_DIAGRAM.md +952 -0
- package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +1734 -0
- package/docs/template-engine/esempi-incrementali.js +192 -0
- package/docs/template-engine/examples/esempio1-nessun-dato.ejs +12 -0
- package/docs/template-engine/examples/esempio2-una-variabile.ejs +11 -0
- package/docs/template-engine/examples/esempio3-piu-variabili.ejs +15 -0
- package/docs/template-engine/examples/esempio4-condizionale.ejs +18 -0
- package/docs/template-engine/examples/esempio5-loop.ejs +18 -0
- package/docs/template-engine/examples/index-esempi.html +181 -0
- package/docs/template-engine/examples/index.html +40 -0
- package/docs/template-engine/examples/test.ejs +64 -0
- package/index.cjs +186 -35
- package/package.json +9 -6
- package/CREATE_RELEASE.sh +0 -53
- package/publish-to-npm.sh +0 -65
- /package/{benchmark-results-baseline-v1.2.0.txt → __tests__/benchmark-results-baseline-v1.2.0.txt} +0 -0
- /package/{benchmark-results-optimized-v2.0.0.txt → __tests__/benchmark-results-optimized-v2.0.0.txt} +0 -0
- /package/{benchmark.js → __tests__/benchmark.js} +0 -0
- /package/{customTest → __tests__/customTest}/README.md +0 -0
- /package/{customTest → __tests__/customTest}/loadConfig.util.js +0 -0
- /package/{customTest → __tests__/customTest}/serversToLoad.util.js +0 -0
- /package/{demo-regex-index.js → __tests__/demo-regex-index.js} +0 -0
- /package/{test-regex-quick.js → __tests__/test-regex-quick.js} +0 -0
- /package/{BENCHMARKS.md → docs/BENCHMARKS.md} +0 -0
- /package/{CHANGELOG.md → docs/CHANGELOG.md} +0 -0
- /package/{DEBUG_REPORT.md → docs/DEBUG_REPORT.md} +0 -0
- /package/{DOCUMENTATION.md → docs/DOCUMENTATION.md} +0 -0
- /package/{EXAMPLES_INDEX_OPTION.md → docs/EXAMPLES_INDEX_OPTION.md} +0 -0
- /package/{INDEX_OPTION_PRIORITY.md → docs/INDEX_OPTION_PRIORITY.md} +0 -0
- /package/{OPTIMIZATION_HTTP_CACHING.md → docs/OPTIMIZATION_HTTP_CACHING.md} +0 -0
- /package/{PERFORMANCE_ANALYSIS.md → docs/PERFORMANCE_ANALYSIS.md} +0 -0
- /package/{PERFORMANCE_COMPARISON.md → docs/PERFORMANCE_COMPARISON.md} +0 -0
- /package/{noteExports.md → docs/noteExports.md} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="it">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>EJS Loop Test</title>
|
|
6
|
+
</head>
|
|
7
|
+
<body>
|
|
8
|
+
<h1>Lista di Items</h1>
|
|
9
|
+
<ul>
|
|
10
|
+
<% items.forEach(function(item, index) { %>
|
|
11
|
+
<li data-index="<%= index %>"><%= item.name %> - <%= item.value %></li>
|
|
12
|
+
<% }); %>
|
|
13
|
+
</ul>
|
|
14
|
+
<p>Totale items: <%= items.length %></p>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Code Review - koa-classic-server
|
|
2
|
+
|
|
3
|
+
## Analisi Generale del Codice
|
|
4
|
+
|
|
5
|
+
Data: 2025-11-18
|
|
6
|
+
File analizzato: `index.cjs` (651 righe)
|
|
7
|
+
Test: 146 passing ✅
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 📊 Sommario
|
|
12
|
+
|
|
13
|
+
| Categoria | Stato | Note |
|
|
14
|
+
|-----------|-------|------|
|
|
15
|
+
| Indentazione | ✅ Ottima | Consistente a 4 spazi |
|
|
16
|
+
| Gestione errori | ✅ Ottima | Try/catch completi |
|
|
17
|
+
| Sicurezza | ✅ Ottima | Path traversal, XSS protection |
|
|
18
|
+
| Performance | ✅ Ottima | Async/await, array join |
|
|
19
|
+
| Test coverage | ✅ Ottima | 146 test passano |
|
|
20
|
+
| **Operatori confronto** | ⚠️ **Da migliorare** | Uso misto di `==` e `===` |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## ⚠️ Problemi Trovati
|
|
25
|
+
|
|
26
|
+
### 1. Uso Inconsistente di == vs ===
|
|
27
|
+
|
|
28
|
+
**Problema:** Il codice usa sia `==` che `===` in modo inconsistente.
|
|
29
|
+
|
|
30
|
+
**Impatto:** Medio - Può causare bug sottili dovuti alla type coercion JavaScript.
|
|
31
|
+
|
|
32
|
+
**Occorrenze trovate:** ~25 istanze
|
|
33
|
+
|
|
34
|
+
#### Esempi:
|
|
35
|
+
|
|
36
|
+
**Linea 68:**
|
|
37
|
+
```javascript
|
|
38
|
+
// ❌ Attuale
|
|
39
|
+
options.showDirContents = typeof options.showDirContents == 'boolean' ? options.showDirContents : true;
|
|
40
|
+
|
|
41
|
+
// ✅ Suggerito
|
|
42
|
+
options.showDirContents = typeof options.showDirContents === 'boolean' ? options.showDirContents : true;
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Linea 112:**
|
|
46
|
+
```javascript
|
|
47
|
+
// ❌ Attuale
|
|
48
|
+
if (ctx.href.charAt(ctx.href.length - 1) == '/') {
|
|
49
|
+
|
|
50
|
+
// ✅ Suggerito
|
|
51
|
+
if (ctx.href.charAt(ctx.href.length - 1) === '/') {
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Linea 123:**
|
|
55
|
+
```javascript
|
|
56
|
+
// ❌ Attuale
|
|
57
|
+
if (a_urlPrefix[key] != a_pathname[key]) {
|
|
58
|
+
|
|
59
|
+
// ✅ Suggerito
|
|
60
|
+
if (a_urlPrefix[key] !== a_pathname[key]) {
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Linea 470:**
|
|
64
|
+
```javascript
|
|
65
|
+
// ❌ Attuale
|
|
66
|
+
if (dir.length == 0) {
|
|
67
|
+
|
|
68
|
+
// ✅ Suggerito
|
|
69
|
+
if (dir.length === 0) {
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Linea 500:**
|
|
73
|
+
```javascript
|
|
74
|
+
// ❌ Attuale
|
|
75
|
+
if (type == 1) {
|
|
76
|
+
|
|
77
|
+
// ✅ Suggerito
|
|
78
|
+
if (type === 1) {
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### 2. Lista Completa Sostituzioni Richieste
|
|
84
|
+
|
|
85
|
+
#### typeof comparisons (5 occorrenze):
|
|
86
|
+
```javascript
|
|
87
|
+
Linea 68: typeof options.showDirContents == 'boolean' → ===
|
|
88
|
+
Linea 71: typeof options.index == 'string' → ===
|
|
89
|
+
Linea 94: typeof options.urlPrefix == 'string' → ===
|
|
90
|
+
Linea 96: options.template.render == undefined → ===
|
|
91
|
+
Linea 96: typeof options.template.render == 'function' → ===
|
|
92
|
+
Linea 100: typeof options.cacheMaxAge == 'number' → ===
|
|
93
|
+
Linea 101: typeof options.enableCaching == 'boolean' → ===
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### String comparisons (5 occorrenze):
|
|
97
|
+
```javascript
|
|
98
|
+
Linea 112: ctx.href.charAt(ctx.href.length - 1) == '/' → ===
|
|
99
|
+
Linea 123: a_urlPrefix[key] != a_pathname[key] → !==
|
|
100
|
+
Linea 131: options.urlPrefix != "" → !==
|
|
101
|
+
Linea 152: pageHrefOutPrefix.pathname == "/" → ===
|
|
102
|
+
Linea 462: pageHrefOutPrefix.origin + "/" != pageHrefOutPrefix.href → !==
|
|
103
|
+
Linea 489: pageHref.href == pageHref.origin + options.urlPrefix + "/" → ===
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### Number comparisons (8 occorrenze):
|
|
107
|
+
```javascript
|
|
108
|
+
Linea 142: a_pathnameOutPrefix[1] == value.substring(1) → ===
|
|
109
|
+
Linea 470: dir.length == 0 → ===
|
|
110
|
+
Linea 482: type !== 1 && type !== 2 && type !== 3 → ✅ già corretto
|
|
111
|
+
Linea 500: type == 1 → ===
|
|
112
|
+
Linea 510: type == 2 → ===
|
|
113
|
+
Linea 511: type == 2 || type == 3 → === (2 volte)
|
|
114
|
+
Linea 532: a.type === 2 → ✅ già corretto
|
|
115
|
+
Linea 534: a.type !== 2 && b.type === 2 → ✅ già corretto
|
|
116
|
+
Linea 542: a.type === 2 && b.type !== 2 → ✅ già corretto
|
|
117
|
+
Linea 557: item.type == 1 → ===
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## ✅ Punti di Forza
|
|
123
|
+
|
|
124
|
+
### 1. Sicurezza
|
|
125
|
+
- ✅ Path traversal protection completa (linea 149-168)
|
|
126
|
+
- ✅ XSS protection con `escapeHtml()` (linea 524-534)
|
|
127
|
+
- ✅ Content-Disposition properly quoted (linea 379-383)
|
|
128
|
+
- ✅ Validazione input robusta
|
|
129
|
+
|
|
130
|
+
### 2. Performance
|
|
131
|
+
- ✅ Tutte le operazioni I/O sono async (non bloccanti)
|
|
132
|
+
- ✅ String concatenation sostituita con array join
|
|
133
|
+
- ✅ HTTP caching con ETag e Last-Modified
|
|
134
|
+
- ✅ Conditional requests (304 Not Modified)
|
|
135
|
+
|
|
136
|
+
### 3. Gestione Errori
|
|
137
|
+
- ✅ Try/catch su tutte le operazioni async
|
|
138
|
+
- ✅ Status code corretti (404, 403, 500)
|
|
139
|
+
- ✅ Gestione race conditions
|
|
140
|
+
- ✅ Fallback appropriati
|
|
141
|
+
|
|
142
|
+
### 4. Codice Pulito
|
|
143
|
+
- ✅ Indentazione consistente (4 spazi)
|
|
144
|
+
- ✅ Commenti chiari e utili
|
|
145
|
+
- ✅ Nomi variabili descrittivi
|
|
146
|
+
- ✅ Funzioni ben separate
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 💡 Raccomandazioni
|
|
151
|
+
|
|
152
|
+
### Priorità Alta
|
|
153
|
+
|
|
154
|
+
1. **Standardizzare operatori di confronto**
|
|
155
|
+
- Sostituire tutti i `==` con `===`
|
|
156
|
+
- Sostituire tutti i `!=` con `!==`
|
|
157
|
+
- Motivo: Prevenire bug dovuti a type coercion
|
|
158
|
+
- Tempo stimato: 10-15 minuti
|
|
159
|
+
- Rischio: Basso (test coprono il comportamento)
|
|
160
|
+
|
|
161
|
+
### Priorità Media
|
|
162
|
+
|
|
163
|
+
2. **Aggiungere JSDoc comments**
|
|
164
|
+
```javascript
|
|
165
|
+
/**
|
|
166
|
+
* Find index file in directory with priority support
|
|
167
|
+
* @param {string} dirPath - Directory path to search
|
|
168
|
+
* @param {Array<string|RegExp>} indexPatterns - Array of patterns
|
|
169
|
+
* @returns {Promise<{name: string, stat: fs.Stats}|null>}
|
|
170
|
+
*/
|
|
171
|
+
async function findIndexFile(dirPath, indexPatterns) {
|
|
172
|
+
// ...
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
3. **Separare funzioni helper in moduli**
|
|
177
|
+
- `escapeHtml()` → `lib/htmlUtils.js`
|
|
178
|
+
- `formatSize()` → `lib/formatUtils.js`
|
|
179
|
+
- Miglior organizzazione e testabilità
|
|
180
|
+
|
|
181
|
+
### Priorità Bassa
|
|
182
|
+
|
|
183
|
+
4. **Aggiungere TypeScript definitions** (`index.d.ts`)
|
|
184
|
+
5. **Considerare ESLint** per standardizzazione automatica
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## 🧪 Verifica Sicurezza
|
|
189
|
+
|
|
190
|
+
### Path Traversal Protection ✅
|
|
191
|
+
```javascript
|
|
192
|
+
// Linea 149-168
|
|
193
|
+
const normalizedPath = path.normalize(requestedPath);
|
|
194
|
+
const fullPath = path.join(normalizedRootDir, normalizedPath);
|
|
195
|
+
|
|
196
|
+
// Security check: ensure resolved path is within rootDir
|
|
197
|
+
if (!fullPath.startsWith(normalizedRootDir)) {
|
|
198
|
+
ctx.status = 403;
|
|
199
|
+
ctx.body = 'Forbidden';
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
**Valutazione:** Eccellente. Protegge da `../../../etc/passwd` attacks.
|
|
204
|
+
|
|
205
|
+
### XSS Protection ✅
|
|
206
|
+
```javascript
|
|
207
|
+
// Linea 524-534
|
|
208
|
+
function escapeHtml(unsafe) {
|
|
209
|
+
if (typeof unsafe !== 'string') {
|
|
210
|
+
return unsafe;
|
|
211
|
+
}
|
|
212
|
+
return unsafe
|
|
213
|
+
.replace(/&/g, "&")
|
|
214
|
+
.replace(/</g, "<")
|
|
215
|
+
.replace(/>/g, ">")
|
|
216
|
+
.replace(/"/g, """)
|
|
217
|
+
.replace(/'/g, "'");
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
**Valutazione:** Eccellente. Previene XSS in directory listing.
|
|
221
|
+
|
|
222
|
+
### Race Condition Protection ✅
|
|
223
|
+
```javascript
|
|
224
|
+
// Linea 174-181
|
|
225
|
+
try {
|
|
226
|
+
stat = await fs.promises.stat(toOpen);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
ctx.status = 404;
|
|
229
|
+
ctx.body = requestedUrlNotFound();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
**Valutazione:** Buona. Gestisce correttamente file cancellati tra check ed access.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 📈 Metriche Codice
|
|
238
|
+
|
|
239
|
+
| Metrica | Valore | Valutazione |
|
|
240
|
+
|---------|--------|-------------|
|
|
241
|
+
| Linee codice | 651 | ✅ Appropriato |
|
|
242
|
+
| Complessità ciclomatica | Bassa | ✅ Ottimo |
|
|
243
|
+
| Funzioni async | 100% | ✅ Eccellente |
|
|
244
|
+
| Copertura test | Alta | ✅ Eccellente |
|
|
245
|
+
| Dipendenze | 4 | ✅ Minime |
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 🎯 Piano d'Azione Suggerito
|
|
250
|
+
|
|
251
|
+
### Step 1: Fix operatori confronto (15 min)
|
|
252
|
+
```bash
|
|
253
|
+
# Trova tutte le occorrenze
|
|
254
|
+
grep -n " == " index.cjs
|
|
255
|
+
grep -n " != " index.cjs
|
|
256
|
+
|
|
257
|
+
# Sostituisci manualmente o con script
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Step 2: Verifica test (2 min)
|
|
261
|
+
```bash
|
|
262
|
+
npm test
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Step 3: Commit (1 min)
|
|
266
|
+
```bash
|
|
267
|
+
git add index.cjs
|
|
268
|
+
git commit -m "Standardize comparison operators (== to ===, != to !==)"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## 📝 Note Finali
|
|
274
|
+
|
|
275
|
+
Il codice è **globalmente di ottima qualità**:
|
|
276
|
+
- ✅ Sicuro
|
|
277
|
+
- ✅ Performante
|
|
278
|
+
- ✅ Ben testato
|
|
279
|
+
- ✅ Ben strutturato
|
|
280
|
+
|
|
281
|
+
L'unico miglioramento significativo è la **standardizzazione degli operatori di confronto** da `==` a `===`, che è una best practice JavaScript universalmente riconosciuta.
|
|
282
|
+
|
|
283
|
+
**Rischio di modifiche:** Basso
|
|
284
|
+
- I test esistenti coprono il comportamento
|
|
285
|
+
- Le modifiche sono meccaniche
|
|
286
|
+
- Nessun cambio di logica
|
|
287
|
+
|
|
288
|
+
**Benefici:**
|
|
289
|
+
- Codice più robusto
|
|
290
|
+
- Prevenzione bug futuri
|
|
291
|
+
- Conformità best practices
|
|
292
|
+
- Migliore leggibilità
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
**Review by:** Claude Code Assistant
|
|
297
|
+
**Date:** 2025-11-18
|
|
298
|
+
**Status:** ⚠️ Minor issues found - Easy fixes recommended
|