koa-classic-server 2.1.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.
Files changed (2) hide show
  1. package/README.md +548 -136
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,48 +1,75 @@
1
1
  # koa-classic-server
2
2
 
3
- ๐Ÿ”’ **Secure Koa middleware for serving static files** with Apache-like directory listing, template engine support, and comprehensive security fixes.
3
+ ๐Ÿš€ **Production-ready Koa middleware** for serving static files with Apache2-like directory listing, sortable columns, HTTP caching, template engine support, and enterprise-grade security.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/koa-classic-server.svg)](https://www.npmjs.com/package/koa-classic-server)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Tests](https://img.shields.io/badge/tests-146%20passing-brightgreen.svg)]()
7
+ [![Tests](https://img.shields.io/badge/tests-153%20passing-brightgreen.svg)]()
8
8
 
9
- ## โš ๏ธ Version 1.2.0 - Critical Security Update
9
+ ---
10
+
11
+ ## ๐ŸŽ‰ Version 2.1.2 - Production Release
12
+
13
+ Version 2.1.2 is a **major production release** featuring performance optimizations, enhanced directory listing, and critical bug fixes.
14
+
15
+ ### What's New in 2.1.2
10
16
 
11
- Version 1.2.0 includes **critical security fixes** for path traversal vulnerabilities and other important improvements. **Upgrade immediately** if you're using version 1.1.0 or earlier.
17
+ โœ… **Sortable Directory Columns** - Click Name/Type/Size to sort (Apache2-like)
18
+ โœ… **Navigation Bug Fixed** - Directory navigation now works correctly after sorting
19
+ โœ… **File Size Display** - Human-readable file sizes (B, KB, MB, GB, TB)
20
+ โœ… **HTTP Caching** - 80-95% bandwidth reduction with ETag and Last-Modified
21
+ โœ… **Async/Await** - Non-blocking I/O for high performance
22
+ โœ… **153 Tests Passing** - Comprehensive test coverage
23
+ โœ… **Flow Documentation** - Complete execution flow diagrams
24
+ โœ… **Code Review** - Standardized operators and best practices
12
25
 
13
- ### What's New in 1.2.0
26
+ ### What's New in 2.0
14
27
 
15
- โœ… **Fixed Path Traversal Vulnerability** - No more unauthorized file access
16
- โœ… **Proper HTTP 404 Status Codes** - Standards-compliant error handling
17
- โœ… **Template Error Handling** - No more server crashes
18
- โœ… **XSS Protection** - HTML escaping in directory listings
19
- โœ… **Race Condition Fixes** - Robust file access
20
- โœ… **146 Tests Passing** - Comprehensive test coverage including EJS integration
28
+ โœ… **Performance Optimizations** - 50-70% faster directory listings
29
+ โœ… **Enhanced Index Option** - Array format with RegExp support
30
+ โœ… **Template Engine Guide** - Complete documentation with examples
31
+ โœ… **Security Hardened** - Path traversal, XSS, race condition fixes
21
32
 
22
- [See full changelog](./docs/CHANGELOG.md)
33
+ [See full changelog โ†’](./docs/CHANGELOG.md)
34
+
35
+ ---
23
36
 
24
37
  ## Features
25
38
 
26
- koa-classic-server is a middleware for serving static files from a directory with Apache 2-like behavior. The contents of a folder on the server will be shown remotely and if you want to access a file, click on it.
39
+ **koa-classic-server** is a high-performance middleware for serving static files with Apache2-like behavior, making file browsing intuitive and powerful.
27
40
 
28
- **Key Features:**
41
+ ### Core Features
29
42
 
30
- - ๐Ÿ—‚๏ธ **Directory Listing** - Apache-style browseable directories
31
- - ๐Ÿ“„ **Static File Serving** - Automatic MIME type detection
32
- - ๐ŸŽจ **Template Engine Support** - Integrate EJS, Pug, Handlebars, etc.
33
- - ๐Ÿ”’ **Security** - Path traversal protection, XSS prevention
34
- - โš™๏ธ **Configurable** - URL prefixes, reserved paths, index files
35
- - ๐Ÿงช **Well-Tested** - 146 tests with comprehensive coverage (security, EJS, performance)
43
+ - ๐Ÿ—‚๏ธ **Apache2-like Directory Listing** - Sortable columns (Name, Type, Size)
44
+ - ๐Ÿ“„ **Static File Serving** - Automatic MIME type detection with streaming
45
+ - ๐Ÿ“Š **Sortable Columns** - Click headers to sort ascending/descending
46
+ - ๐Ÿ“ **File Sizes** - Human-readable display (B, KB, MB, GB, TB)
47
+ - โšก **HTTP Caching** - ETag, Last-Modified, 304 responses
48
+ - ๐ŸŽจ **Template Engine Support** - EJS, Pug, Handlebars, Nunjucks, etc.
49
+ - ๐Ÿ”’ **Enterprise Security** - Path traversal, XSS, race condition protection
50
+ - โš™๏ธ **Highly Configurable** - URL prefixes, reserved paths, index files
51
+ - ๐Ÿš€ **High Performance** - Async/await, non-blocking I/O, optimized algorithms
52
+ - ๐Ÿงช **Well-Tested** - 153 passing tests with comprehensive coverage
36
53
  - ๐Ÿ“ฆ **Dual Module Support** - CommonJS and ES Modules
37
54
 
55
+ ---
56
+
38
57
  ## Installation
39
58
 
40
59
  ```bash
41
60
  npm install koa-classic-server
42
61
  ```
43
62
 
63
+ **Requirements:**
64
+ - Node.js >= 12.0.0
65
+ - Koa >= 2.0.0
66
+
67
+ ---
68
+
44
69
  ## Quick Start
45
70
 
71
+ ### Basic Usage
72
+
46
73
  ```javascript
47
74
  const Koa = require('koa');
48
75
  const koaClassicServer = require('koa-classic-server');
@@ -56,9 +83,30 @@ app.listen(3000);
56
83
  console.log('Server running on http://localhost:3000');
57
84
  ```
58
85
 
59
- ## Usage
86
+ ### With Options
60
87
 
61
- ### Import
88
+ ```javascript
89
+ const Koa = require('koa');
90
+ const koaClassicServer = require('koa-classic-server');
91
+
92
+ const app = new Koa();
93
+
94
+ app.use(koaClassicServer(__dirname + '/public', {
95
+ showDirContents: true,
96
+ index: ['index.html', 'index.htm'],
97
+ urlPrefix: '/static',
98
+ cacheMaxAge: 3600,
99
+ enableCaching: true
100
+ }));
101
+
102
+ app.listen(3000);
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Complete Usage Guide
108
+
109
+ ### 1. Import
62
110
 
63
111
  ```javascript
64
112
  // CommonJS
@@ -68,9 +116,9 @@ const koaClassicServer = require('koa-classic-server');
68
116
  import koaClassicServer from 'koa-classic-server';
69
117
  ```
70
118
 
71
- ### Basic Examples
119
+ ### 2. Basic File Server
72
120
 
73
- #### Example 1: Simple File Server
121
+ Serve static files from a directory:
74
122
 
75
123
  ```javascript
76
124
  const Koa = require('koa');
@@ -80,57 +128,173 @@ const app = new Koa();
80
128
 
81
129
  app.use(koaClassicServer(__dirname + '/public', {
82
130
  showDirContents: true,
83
- index: ['index.html'] // Array format (recommended)
131
+ index: ['index.html']
84
132
  }));
85
133
 
86
134
  app.listen(3000);
87
135
  ```
88
136
 
89
- #### Example 2: With URL Prefix
137
+ **What it does:**
138
+ - Serves files from `/public` directory
139
+ - Shows directory listing when accessing folders
140
+ - Looks for `index.html` in directories
141
+ - Sortable columns (Name, Type, Size)
142
+ - File sizes displayed in human-readable format
90
143
 
91
- ```javascript
92
- const Koa = require('koa');
93
- const koaClassicServer = require('koa-classic-server');
144
+ ### 3. With URL Prefix
94
145
 
95
- const app = new Koa();
146
+ Serve files under a specific URL path:
96
147
 
97
- // Files accessible under /static
98
- // e.g., http://localhost:3000/static/image.png
99
- app.use(koaClassicServer(__dirname + '/public', {
148
+ ```javascript
149
+ app.use(koaClassicServer(__dirname + '/assets', {
100
150
  urlPrefix: '/static',
101
151
  showDirContents: true
102
152
  }));
153
+ ```
103
154
 
104
- app.listen(3000);
155
+ **Result:**
156
+ - `http://localhost:3000/static/image.png` โ†’ serves `/assets/image.png`
157
+ - `http://localhost:3000/static/` โ†’ shows `/assets` directory listing
158
+
159
+ ### 4. With Reserved Paths
160
+
161
+ Protect specific directories from being accessed:
162
+
163
+ ```javascript
164
+ app.use(koaClassicServer(__dirname + '/www', {
165
+ urlsReserved: ['/admin', '/config', '/.git', '/node_modules']
166
+ }));
105
167
  ```
106
168
 
107
- #### Example 3: With Template Engine (EJS)
169
+ **Result:**
170
+ - `/admin/*` โ†’ passed to next middleware (not served)
171
+ - `/config/*` โ†’ protected
172
+ - Other paths โ†’ served normally
173
+
174
+ ### 5. With Template Engine (EJS)
175
+
176
+ Dynamically render templates with data:
108
177
 
109
178
  ```javascript
110
- const Koa = require('koa');
111
- const koaClassicServer = require('koa-classic-server');
112
179
  const ejs = require('ejs');
113
- const fs = require('fs').promises;
114
-
115
- const app = new Koa();
116
180
 
117
181
  app.use(koaClassicServer(__dirname + '/views', {
118
182
  template: {
119
- ext: ['ejs'], // File extensions to process
183
+ ext: ['ejs', 'html.ejs'],
120
184
  render: async (ctx, next, filePath) => {
121
- // Read template file
122
- const templateContent = await fs.readFile(filePath, 'utf-8');
123
-
124
- // Render with data
125
- const html = ejs.render(templateContent, {
185
+ const data = {
126
186
  title: 'My App',
127
187
  user: ctx.state.user || { name: 'Guest' },
128
- path: ctx.path,
188
+ items: ['Item 1', 'Item 2', 'Item 3'],
129
189
  timestamp: new Date().toISOString()
130
- });
190
+ };
131
191
 
192
+ ctx.body = await ejs.renderFile(filePath, data);
132
193
  ctx.type = 'text/html';
133
- ctx.body = html;
194
+ }
195
+ }
196
+ }));
197
+ ```
198
+
199
+ **Template example (`views/dashboard.ejs`):**
200
+ ```html
201
+ <!DOCTYPE html>
202
+ <html>
203
+ <head>
204
+ <title><%= title %></title>
205
+ </head>
206
+ <body>
207
+ <h1>Welcome, <%= user.name %>!</h1>
208
+ <ul>
209
+ <% items.forEach(item => { %>
210
+ <li><%= item %></li>
211
+ <% }); %>
212
+ </ul>
213
+ <p>Generated at: <%= timestamp %></p>
214
+ </body>
215
+ </html>
216
+ ```
217
+
218
+ **See complete guide:** [Template Engine Documentation โ†’](./docs/template-engine/TEMPLATE_ENGINE_GUIDE.md)
219
+
220
+ ### 6. With HTTP Caching
221
+
222
+ Enable aggressive caching for static files:
223
+
224
+ ```javascript
225
+ app.use(koaClassicServer(__dirname + '/public', {
226
+ enableCaching: true, // Enable ETag and Last-Modified
227
+ cacheMaxAge: 86400, // Cache for 24 hours (in seconds)
228
+ }));
229
+ ```
230
+
231
+ **Benefits:**
232
+ - 80-95% bandwidth reduction
233
+ - 304 Not Modified responses for unchanged files
234
+ - Faster page loads for returning visitors
235
+
236
+ **See details:** [HTTP Caching Optimization โ†’](./docs/OPTIMIZATION_HTTP_CACHING.md)
237
+
238
+ ### 7. Multiple Index Files with Priority
239
+
240
+ Search for multiple index files with custom order:
241
+
242
+ ```javascript
243
+ app.use(koaClassicServer(__dirname + '/public', {
244
+ index: [
245
+ 'index.html', // First priority
246
+ 'index.htm', // Second priority
247
+ /index\.[eE][jJ][sS]/, // Third: index.ejs (case-insensitive)
248
+ 'default.html' // Last priority
249
+ ]
250
+ }));
251
+ ```
252
+
253
+ **See details:** [Index Option Priority โ†’](./docs/INDEX_OPTION_PRIORITY.md)
254
+
255
+ ### 8. Complete Production Example
256
+
257
+ Real-world configuration for production:
258
+
259
+ ```javascript
260
+ const Koa = require('koa');
261
+ const koaClassicServer = require('koa-classic-server');
262
+ const ejs = require('ejs');
263
+ const path = require('path');
264
+
265
+ const app = new Koa();
266
+
267
+ // Serve static assets with caching
268
+ app.use(koaClassicServer(path.join(__dirname, 'public'), {
269
+ method: ['GET', 'HEAD'],
270
+ showDirContents: false, // Disable directory listing in production
271
+ index: ['index.html', 'index.htm'],
272
+ urlPrefix: '/assets',
273
+ urlsReserved: ['/admin', '/api', '/.git'],
274
+ enableCaching: true,
275
+ cacheMaxAge: 86400, // 24 hours
276
+ }));
277
+
278
+ // Serve dynamic templates
279
+ app.use(koaClassicServer(path.join(__dirname, 'views'), {
280
+ showDirContents: false,
281
+ template: {
282
+ ext: ['ejs'],
283
+ render: async (ctx, next, filePath) => {
284
+ const data = {
285
+ env: process.env.NODE_ENV,
286
+ user: ctx.state.user,
287
+ config: ctx.state.config
288
+ };
289
+
290
+ try {
291
+ ctx.body = await ejs.renderFile(filePath, data);
292
+ ctx.type = 'text/html';
293
+ } catch (error) {
294
+ console.error('Template error:', error);
295
+ ctx.status = 500;
296
+ ctx.body = 'Internal Server Error';
297
+ }
134
298
  }
135
299
  }
136
300
  }));
@@ -138,9 +302,9 @@ app.use(koaClassicServer(__dirname + '/views', {
138
302
  app.listen(3000);
139
303
  ```
140
304
 
141
- See **[Template Engine Guide](./docs/template-engine/TEMPLATE_ENGINE_GUIDE.md)** for comprehensive template engine documentation with progressive examples.
305
+ ---
142
306
 
143
- ## API
307
+ ## API Reference
144
308
 
145
309
  ### koaClassicServer(rootDir, options)
146
310
 
@@ -148,56 +312,54 @@ Creates a Koa middleware for serving static files.
148
312
 
149
313
  **Parameters:**
150
314
 
151
- - `rootDir` (String, required): Absolute path to the directory containing static files
152
- - `options` (Object, optional): Configuration options
315
+ - **`rootDir`** (String, required): Absolute path to the directory containing files
316
+ - **`options`** (Object, optional): Configuration options
153
317
 
154
318
  **Returns:** Koa middleware function
155
319
 
156
- ## Options
320
+ ### Options
157
321
 
158
322
  ```javascript
159
- const options = {
323
+ {
160
324
  // HTTP methods allowed (default: ['GET'])
161
325
  method: ['GET', 'HEAD'],
162
326
 
163
327
  // Show directory contents (default: true)
164
328
  showDirContents: true,
165
329
 
166
- // Index file configuration (default: [])
167
- // RECOMMENDED: Use array format (string format is deprecated)
168
- // Formats:
169
- // - Array of strings: ['index.html', 'index.htm', 'default.html']
170
- // - Array of RegExp: [/index\.html/i] (case-insensitive)
171
- // - Mixed array: ['index.html', /INDEX\.HTM/i]
172
- // Priority: First match wins (array order determines search priority)
173
- //
174
- // DEPRECATED: String format 'index.html' still works but will be removed
175
- // in future versions. Please use array format: ['index.html']
176
- //
177
- // See INDEX_OPTION_PRIORITY.md for detailed behavior documentation
178
- index: ['index.html'],
330
+ // Index file configuration
331
+ // Array format (recommended):
332
+ // - Strings: exact matches ['index.html', 'default.html']
333
+ // - RegExp: pattern matches [/index\.html/i]
334
+ // - Mixed: ['index.html', /INDEX\.HTM/i]
335
+ // Priority determined by array order (first match wins)
336
+ // See docs/INDEX_OPTION_PRIORITY.md for details
337
+ index: ['index.html', 'index.htm'],
179
338
 
180
339
  // URL path prefix (default: '')
181
- // Files will be served under this prefix
340
+ // Files served under this prefix
182
341
  urlPrefix: '/static',
183
342
 
184
343
  // Reserved paths (default: [])
185
- // These directories won't be accessible
186
- // Note: Only works for first-level directories
187
- urlsReserved: ['/admin', '/private'],
344
+ // First-level directories passed to next middleware
345
+ urlsReserved: ['/admin', '/api', '/.git'],
188
346
 
189
347
  // Template engine configuration
190
348
  template: {
191
349
  // Template rendering function
192
350
  render: async (ctx, next, filePath) => {
193
351
  // Your rendering logic
194
- ctx.body = await yourTemplateEngine.render(filePath, data);
352
+ ctx.body = await yourEngine.render(filePath, data);
195
353
  },
196
354
 
197
- // File extensions to process with template.render
355
+ // File extensions to process
198
356
  ext: ['ejs', 'pug', 'hbs']
199
- }
200
- };
357
+ },
358
+
359
+ // HTTP caching configuration
360
+ enableCaching: true, // Enable ETag & Last-Modified (default: true)
361
+ cacheMaxAge: 3600, // Cache-Control max-age in seconds (default: 3600 = 1 hour)
362
+ }
201
363
  ```
202
364
 
203
365
  ### Options Details
@@ -206,133 +368,383 @@ const options = {
206
368
  |--------|------|---------|-------------|
207
369
  | `method` | Array | `['GET']` | Allowed HTTP methods |
208
370
  | `showDirContents` | Boolean | `true` | Show directory listing |
209
- | `index` | String | `''` | Index file name |
371
+ | `index` | Array/String | `[]` | Index file patterns (array format recommended) |
210
372
  | `urlPrefix` | String | `''` | URL path prefix |
211
- | `urlsReserved` | Array | `[]` | Reserved directory paths |
373
+ | `urlsReserved` | Array | `[]` | Reserved directory paths (first-level only) |
212
374
  | `template.render` | Function | `undefined` | Template rendering function |
213
375
  | `template.ext` | Array | `[]` | Extensions for template rendering |
376
+ | `enableCaching` | Boolean | `true` | Enable HTTP caching headers |
377
+ | `cacheMaxAge` | Number | `3600` | Cache duration in seconds |
378
+
379
+ ---
380
+
381
+ ## Directory Listing Features
382
+
383
+ ### Sortable Columns
384
+
385
+ Click on column headers to sort:
386
+
387
+ - **Name** - Alphabetical sorting (A-Z or Z-A)
388
+ - **Type** - Sort by MIME type (directories always first)
389
+ - **Size** - Sort by file size (directories always first)
390
+
391
+ Visual indicators:
392
+ - **โ†‘** - Ascending order
393
+ - **โ†“** - Descending order
394
+
395
+ ### File Size Display
396
+
397
+ Human-readable format:
398
+ - `1.5 KB` - Kilobytes
399
+ - `2.3 MB` - Megabytes
400
+ - `1.2 GB` - Gigabytes
401
+ - `-` - Directories (no size)
402
+
403
+ ### Navigation
404
+
405
+ - **Click folder name** - Enter directory
406
+ - **Click file name** - Download/view file
407
+ - **Parent Directory** - Go up one level
408
+
409
+ ---
214
410
 
215
411
  ## Security
216
412
 
217
- ### Path Traversal Protection
413
+ ### Built-in Protection
414
+
415
+ koa-classic-server includes enterprise-grade security:
218
416
 
219
- koa-classic-server 1.2.0 protects against path traversal attacks:
417
+ #### 1. Path Traversal Protection
418
+
419
+ Prevents access to files outside `rootDir`:
220
420
 
221
421
  ```javascript
222
- // โŒ These requests are blocked (return 403 Forbidden)
223
- GET /../../../etc/passwd
224
- GET /../config/database.yml
225
- GET /%2e%2e%2fpackage.json
422
+ // โŒ Blocked requests
423
+ GET /../../../etc/passwd โ†’ 403 Forbidden
424
+ GET /../config/database.yml โ†’ 403 Forbidden
425
+ GET /%2e%2e%2fpackage.json โ†’ 403 Forbidden
226
426
  ```
227
427
 
228
- ### Protected Directories
428
+ #### 2. XSS Protection
229
429
 
230
- Use `urlsReserved` to protect sensitive directories:
430
+ All filenames and paths are HTML-escaped:
231
431
 
232
432
  ```javascript
233
- app.use(koaClassicServer(__dirname + '/www', {
234
- urlsReserved: ['/config', '/private', '/.git', '/node_modules']
433
+ // Malicious filename: <script>alert('xss')</script>.txt
434
+ // Displayed as: &lt;script&gt;alert('xss')&lt;/script&gt;.txt
435
+ // โœ… Safe - script doesn't execute
436
+ ```
437
+
438
+ #### 3. Reserved URLs
439
+
440
+ Protect sensitive directories:
441
+
442
+ ```javascript
443
+ app.use(koaClassicServer(__dirname, {
444
+ urlsReserved: ['/admin', '/config', '/.git', '/node_modules']
235
445
  }));
236
446
  ```
237
447
 
238
- ### XSS Protection
448
+ #### 4. Race Condition Protection
449
+
450
+ File access is verified before streaming:
451
+
452
+ ```javascript
453
+ // File deleted between check and access?
454
+ // โœ… Returns 404 instead of crashing
455
+ ```
456
+
457
+ **See full security audit:** [Security Tests โ†’](./__tests__/security.test.js)
458
+
459
+ ---
460
+
461
+ ## Performance
239
462
 
240
- All filenames and paths in directory listings are HTML-escaped to prevent XSS attacks.
463
+ ### Optimizations
241
464
 
242
- ## Error Handling
465
+ Version 2.x includes major performance improvements:
243
466
 
244
- koa-classic-server properly handles errors:
467
+ - **Async/Await** - Non-blocking I/O, event loop never blocked
468
+ - **Array Join** - 30-40% less memory vs string concatenation
469
+ - **HTTP Caching** - 80-95% bandwidth reduction
470
+ - **Single stat() Call** - No double file system access
471
+ - **Streaming** - Large files streamed efficiently
245
472
 
246
- - **404** - File/directory not found
247
- - **403** - Forbidden (path traversal attempts, reserved directories)
248
- - **500** - Template rendering errors, file access errors
473
+ ### Benchmarks
474
+
475
+ Performance results on directory with 1,000 files:
476
+
477
+ ```
478
+ Before (v1.x): ~350ms per request
479
+ After (v2.x): ~190ms per request
480
+ Improvement: 46% faster
481
+ ```
482
+
483
+ **See detailed benchmarks:** [Performance Analysis โ†’](./docs/PERFORMANCE_ANALYSIS.md)
484
+
485
+ ---
249
486
 
250
487
  ## Testing
251
488
 
489
+ Run the comprehensive test suite:
490
+
252
491
  ```bash
253
492
  # Run all tests
254
493
  npm test
255
494
 
256
495
  # Run security tests only
257
496
  npm run test:security
497
+
498
+ # Run performance benchmarks
499
+ npm run test:performance
258
500
  ```
259
501
 
260
- ## Middleware Behavior
502
+ **Test Coverage:**
503
+ - โœ… 153 tests passing
504
+ - โœ… Security tests (path traversal, XSS, race conditions)
505
+ - โœ… EJS template integration tests
506
+ - โœ… Index option tests (strings, arrays, RegExp)
507
+ - โœ… Performance benchmarks
508
+ - โœ… Directory sorting tests
261
509
 
262
- ### Directory Handling
510
+ ---
263
511
 
264
- 1. If `index` file exists โ†’ serve index file
265
- 2. If `showDirContents: true` โ†’ show directory listing
266
- 3. If `showDirContents: false` โ†’ return 404
512
+ ## Complete Documentation
267
513
 
268
- ### File Handling
514
+ ### Core Documentation
269
515
 
270
- 1. Check if file extension matches `template.ext`
271
- 2. If yes โ†’ call `template.render()`
272
- 3. If no โ†’ serve static file with appropriate MIME type
516
+ - **[DOCUMENTATION.md](./docs/DOCUMENTATION.md)** - Complete API reference and usage guide
517
+ - **[FLOW_DIAGRAM.md](./docs/FLOW_DIAGRAM.md)** - Visual flow diagrams and code execution paths
518
+ - **[CHANGELOG.md](./docs/CHANGELOG.md)** - Version history and release notes
273
519
 
274
- ### Reserved URLs
520
+ ### Template Engine
275
521
 
276
- Requests to reserved paths are passed to the next middleware.
522
+ - **[TEMPLATE_ENGINE_GUIDE.md](./docs/template-engine/TEMPLATE_ENGINE_GUIDE.md)** - Complete guide to template engine integration
523
+ - Progressive examples (simple to enterprise)
524
+ - EJS, Pug, Handlebars, Nunjucks support
525
+ - Best practices and troubleshooting
277
526
 
278
- ## Migration from 1.1.0
527
+ ### Configuration
279
528
 
280
- Upgrading is simple! No code changes required:
529
+ - **[INDEX_OPTION_PRIORITY.md](./docs/INDEX_OPTION_PRIORITY.md)** - Detailed priority behavior for `index` option
530
+ - String vs Array vs RegExp formats
531
+ - Priority order examples
532
+ - Migration guide from v1.x
281
533
 
282
- ```bash
283
- npm update koa-classic-server
284
- ```
534
+ - **[EXAMPLES_INDEX_OPTION.md](./docs/EXAMPLES_INDEX_OPTION.md)** - 10 practical examples of `index` option with RegExp
535
+ - Case-insensitive matching
536
+ - Multiple extensions
537
+ - Complex patterns
285
538
 
286
- **What changed:**
287
- - 404 status codes now correct (was 200)
288
- - Path traversal blocked (was allowed)
289
- - Template errors return 500 (was crash)
539
+ ### Performance
290
540
 
291
- See [CHANGELOG.md](./CHANGELOG.md) for detailed information.
541
+ - **[PERFORMANCE_ANALYSIS.md](./docs/PERFORMANCE_ANALYSIS.md)** - Performance optimization analysis
542
+ - Before/after comparisons
543
+ - Memory usage analysis
544
+ - Bottleneck identification
292
545
 
293
- ## Complete Documentation
546
+ - **[PERFORMANCE_COMPARISON.md](./docs/PERFORMANCE_COMPARISON.md)** - Detailed performance benchmarks
547
+ - Request latency
548
+ - Throughput metrics
549
+ - Concurrent request handling
294
550
 
295
- For complete documentation with all features, examples, troubleshooting, and best practices, see:
551
+ - **[OPTIMIZATION_HTTP_CACHING.md](./docs/OPTIMIZATION_HTTP_CACHING.md)** - HTTP caching implementation details
552
+ - ETag generation
553
+ - Last-Modified headers
554
+ - 304 Not Modified responses
555
+
556
+ - **[BENCHMARKS.md](./docs/BENCHMARKS.md)** - Benchmark results and methodology
557
+
558
+ ### Code Quality
296
559
 
297
- - **[DOCUMENTATION.md](./docs/DOCUMENTATION.md)** - Complete API reference and usage guide
298
- - **[FLOW_DIAGRAM.md](./docs/FLOW_DIAGRAM.md)** - Visual flow diagrams and code execution paths
299
- - **[TEMPLATE_ENGINE_GUIDE.md](./docs/template-engine/TEMPLATE_ENGINE_GUIDE.md)** - Complete guide to template engine integration (EJS, Pug, Handlebars, Nunjucks)
300
- - **[INDEX_OPTION_PRIORITY.md](./docs/INDEX_OPTION_PRIORITY.md)** - Detailed priority behavior for `index` option (string, array, RegExp)
301
- - **[EXAMPLES_INDEX_OPTION.md](./docs/EXAMPLES_INDEX_OPTION.md)** - 10 practical examples of `index` option with RegExp
302
- - **[PERFORMANCE_ANALYSIS.md](./docs/PERFORMANCE_ANALYSIS.md)** - Performance optimization analysis
303
- - **[PERFORMANCE_COMPARISON.md](./docs/PERFORMANCE_COMPARISON.md)** - Before/after performance benchmarks
304
560
  - **[CODE_REVIEW.md](./docs/CODE_REVIEW.md)** - Code quality analysis and review
561
+ - Security audit
562
+ - Best practices
563
+ - Standardization improvements
564
+
565
+ - **[DEBUG_REPORT.md](./docs/DEBUG_REPORT.md)** - Known limitations and debugging info
566
+ - Reserved URLs behavior
567
+ - Edge cases
568
+ - Troubleshooting tips
569
+
570
+ ---
571
+
572
+ ## Migration Guide
573
+
574
+ ### From v1.x to v2.x
575
+
576
+ **Breaking Changes:**
577
+ - `index` option: String format deprecated (still works), use array format
578
+
579
+ **Migration:**
580
+
581
+ ```javascript
582
+ // v1.x (deprecated)
583
+ {
584
+ index: 'index.html'
585
+ }
586
+
587
+ // v2.x (recommended)
588
+ {
589
+ index: ['index.html']
590
+ }
591
+ ```
592
+
593
+ **New Features:**
594
+ - HTTP caching (enabled by default)
595
+ - Sortable directory columns
596
+ - File size display
597
+ - Enhanced index option with RegExp
598
+
599
+ **See full migration guide:** [CHANGELOG.md](./docs/CHANGELOG.md)
600
+
601
+ ---
602
+
603
+ ## Examples
604
+
605
+ ### Example 1: Simple Static Server
606
+
607
+ ```javascript
608
+ const Koa = require('koa');
609
+ const koaClassicServer = require('koa-classic-server');
610
+
611
+ const app = new Koa();
612
+ app.use(koaClassicServer(__dirname + '/public'));
613
+ app.listen(3000);
614
+ ```
615
+
616
+ ### Example 2: Multi-Directory Server
617
+
618
+ ```javascript
619
+ const Koa = require('koa');
620
+ const koaClassicServer = require('koa-classic-server');
621
+
622
+ const app = new Koa();
623
+
624
+ // Serve static assets
625
+ app.use(koaClassicServer(__dirname + '/public', {
626
+ urlPrefix: '/static',
627
+ showDirContents: false
628
+ }));
629
+
630
+ // Serve user uploads
631
+ app.use(koaClassicServer(__dirname + '/uploads', {
632
+ urlPrefix: '/files',
633
+ showDirContents: true
634
+ }));
635
+
636
+ app.listen(3000);
637
+ ```
638
+
639
+ ### Example 3: Development Server with Templates
640
+
641
+ ```javascript
642
+ const Koa = require('koa');
643
+ const koaClassicServer = require('koa-classic-server');
644
+ const ejs = require('ejs');
645
+
646
+ const app = new Koa();
647
+
648
+ // Development mode - show directories
649
+ app.use(koaClassicServer(__dirname + '/src', {
650
+ showDirContents: true,
651
+ template: {
652
+ ext: ['ejs'],
653
+ render: async (ctx, next, filePath) => {
654
+ ctx.body = await ejs.renderFile(filePath, {
655
+ dev: true,
656
+ timestamp: Date.now()
657
+ });
658
+ ctx.type = 'text/html';
659
+ }
660
+ }
661
+ }));
662
+
663
+ app.listen(3000);
664
+ ```
665
+
666
+ ---
667
+
668
+ ## Troubleshooting
669
+
670
+ ### Common Issues
671
+
672
+ **Issue: 404 errors for all files**
673
+
674
+ Check that `rootDir` is an absolute path:
675
+
676
+ ```javascript
677
+ // โŒ Wrong (relative path)
678
+ koaClassicServer('./public')
679
+
680
+ // โœ… Correct (absolute path)
681
+ koaClassicServer(__dirname + '/public')
682
+ koaClassicServer(path.join(__dirname, 'public'))
683
+ ```
684
+
685
+ **Issue: Reserved URLs not working**
686
+
687
+ Reserved URLs only work for first-level directories:
688
+
689
+ ```javascript
690
+ urlsReserved: ['/admin'] // โœ… Blocks /admin/*
691
+ urlsReserved: ['/admin/users'] // โŒ Doesn't work (nested)
692
+ ```
693
+
694
+ **Issue: Directory sorting not working**
695
+
696
+ Make sure you're accessing directories without query params initially. The sorting is applied when you click headers.
697
+
698
+ **See full troubleshooting:** [DEBUG_REPORT.md](./docs/DEBUG_REPORT.md)
699
+
700
+ ---
305
701
 
306
702
  ## Contributing
307
703
 
308
- Contributions are welcome! Please feel free to submit a Pull Request.
704
+ Contributions are welcome! Please:
705
+
706
+ 1. Fork the repository
707
+ 2. Create a feature branch
708
+ 3. Add tests for new functionality
709
+ 4. Ensure all tests pass (`npm test`)
710
+ 5. Submit a pull request
711
+
712
+ ---
309
713
 
310
714
  ## Known Limitations
311
715
 
312
716
  - Reserved URLs only work for first-level directories
717
+ - Template rendering is synchronous per request
313
718
 
314
719
  See [DEBUG_REPORT.md](./docs/DEBUG_REPORT.md) for technical details.
315
720
 
721
+ ---
722
+
316
723
  ## License
317
724
 
318
- MIT
725
+ MIT License - see LICENSE file for details
726
+
727
+ ---
319
728
 
320
729
  ## Author
321
730
 
322
731
  Italo Paesano
323
732
 
324
- ## Changelog
325
-
326
- See [CHANGELOG.md](./CHANGELOG.md)
733
+ ---
327
734
 
328
735
  ## Links
329
736
 
330
- - [Full Documentation](./docs/DOCUMENTATION.md)
331
- - [Debug Report](./docs/DEBUG_REPORT.md)
332
- - [Changelog](./CHANGELOG.md)
333
- - [Repository](https://github.com/italopaesano/koa-classic-server)
334
- - [npm Package](https://www.npmjs.com/package/koa-classic-server)
737
+ - **[npm Package](https://www.npmjs.com/package/koa-classic-server)** - Official npm package
738
+ - **[GitHub Repository](https://github.com/italopaesano/koa-classic-server)** - Source code
739
+ - **[Issue Tracker](https://github.com/italopaesano/koa-classic-server/issues)** - Report bugs
740
+ - **[Full Documentation](./docs/DOCUMENTATION.md)** - Complete reference
741
+
742
+ ---
743
+
744
+ ## Changelog
745
+
746
+ See [CHANGELOG.md](./docs/CHANGELOG.md) for version history.
335
747
 
336
748
  ---
337
749
 
338
- **โš ๏ธ Security Notice:** Version 1.2.0 fixes critical vulnerabilities. Update immediately if using 1.1.0 or earlier.
750
+ **โš ๏ธ Security Notice:** Always use the latest version for security updates and bug fixes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koa-classic-server",
3
- "version": "2.1.0",
3
+ "version": "2.1.2",
4
4
  "description": "High-performance Koa middleware for serving static files with Apache-like directory listing, HTTP caching, template engine support, and comprehensive security fixes",
5
5
  "main": "index.cjs",
6
6
  "exports": {