koa-classic-server 3.0.0-alpha.0 → 3.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/CLAUDE.md +101 -0
- package/README.md +550 -635
- package/__tests__/benchmark-results-v3.0.0.txt +372 -0
- package/__tests__/benchmark.js +1 -1
- package/__tests__/compression.test.js +17 -3
- package/__tests__/customTest/serversToLoad.util.js +4 -4
- package/__tests__/demo-regex-index.js +4 -4
- package/__tests__/directory-sorting-links.test.js +1 -1
- package/__tests__/dt-unknown.test.js +19 -19
- package/__tests__/ejs.test.js +1 -1
- package/__tests__/hidden-option.test.js +48 -63
- package/__tests__/hideExtension.test.js +70 -13
- package/__tests__/index.test.js +6 -6
- package/__tests__/listing.test.js +437 -0
- package/__tests__/logger.test.js +232 -0
- package/__tests__/range.test.js +2 -2
- package/__tests__/security-headers.test.js +20 -8
- package/__tests__/security.test.js +5 -5
- package/__tests__/server-cache.test.js +178 -7
- package/__tests__/symlink.test.js +10 -10
- package/__tests__/template-timeout.test.js +321 -0
- package/docs/CHANGELOG.md +209 -4
- package/docs/CODE_REVIEW.md +2 -0
- package/docs/DOCUMENTATION.md +259 -32
- package/docs/EXAMPLES_INDEX_OPTION.md +1 -1
- package/docs/FLOW_DIAGRAM.md +2 -0
- package/docs/INDEX_OPTION_PRIORITY.md +2 -2
- package/docs/OPTIMIZATION_HTTP_CACHING.md +2 -0
- package/docs/security_improvement_for_V3.md +421 -0
- package/docs/template-engine/TEMPLATE_ENGINE_GUIDE.md +5 -5
- package/docs/template-engine/esempi-incrementali.js +1 -1
- package/index.cjs +551 -178
- package/package.json +6 -1
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI coding assistants working on **koa-classic-server**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Project orientation
|
|
8
|
+
|
|
9
|
+
koa-classic-server is a Koa middleware that serves static files from disk over HTTP, with Apache2-like directory listings, optional template-engine integration, and server-side compressed cache. It is a *classic* file server — its primary job is to take an HTTP request and respond with the file at the requested path, or with a directory listing if a directory is requested without an index file.
|
|
10
|
+
|
|
11
|
+
The project is **not** a framework, not a router, not a CMS. It is intentionally focused.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Design philosophy: HTTP file server first
|
|
16
|
+
|
|
17
|
+
The middleware's primary contract with the operator is:
|
|
18
|
+
|
|
19
|
+
> **"If a file exists in the served directory, `GET` on its path returns it. If a directory is requested without an index file, the listing shows every visible entry."**
|
|
20
|
+
|
|
21
|
+
This contract drives every default. The defaults are picked so that:
|
|
22
|
+
|
|
23
|
+
- Asking for any file under `rootDir` returns it (no silent 404 unless the file truly does not exist).
|
|
24
|
+
- Asking for a directory without an index file returns the listing of that directory.
|
|
25
|
+
- The listing includes every visible entry.
|
|
26
|
+
- No request is silently restricted by some default policy the operator did not ask for.
|
|
27
|
+
|
|
28
|
+
In short: **the operator's directory is the source of truth. The middleware does not second-guess it.**
|
|
29
|
+
|
|
30
|
+
### What this implies for defaults
|
|
31
|
+
|
|
32
|
+
- **Dot-files are visible by default.** Files named `.env`, `.htaccess`, `.well-known/...` are served if requested. If the operator does not want this, they hide them via the `hidden.dotFiles` namespace.
|
|
33
|
+
- **No artificial small-entry limit on directory listings.** If a directory has 5,000 files, the listing shows 5,000 entries. The middleware does NOT decide that "5,000 is too many".
|
|
34
|
+
- **No forced pagination on tiny directories.** Pagination kicks in only when the listing exceeds `dirListing.entriesPerPage`. The default is high enough that most directories render in a single page.
|
|
35
|
+
|
|
36
|
+
### What counts as a "safety net" (acceptable)
|
|
37
|
+
|
|
38
|
+
Some defaults are NOT restrictions on the served content — they are guards against catastrophic failure modes of the **process itself**:
|
|
39
|
+
|
|
40
|
+
| Default | Protects against |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `template.renderTimeout: 30000` | Hung template render blocking the event loop indefinitely |
|
|
43
|
+
| `serverCache.compressedFile.maxSize: 100 MB` | RAM growing unbounded in the compressed-response cache |
|
|
44
|
+
| `dirListing.maxEntries: 100000` | OOM at `readdir()` allocation time on accidentally-huge directories (broken log rotation, mistakenly mounted FS) |
|
|
45
|
+
|
|
46
|
+
These are deliberate exceptions because they protect the process from itself, not the served content. The distinction:
|
|
47
|
+
|
|
48
|
+
- A **safety net** prevents the server from crashing.
|
|
49
|
+
- A **restriction** prevents the operator's intent from being respected.
|
|
50
|
+
|
|
51
|
+
### What restrictions look like (and would NOT be acceptable as defaults)
|
|
52
|
+
|
|
53
|
+
- Hiding files by name pattern (`.env`, `.git`, `secret*`) without the operator opting in.
|
|
54
|
+
- Refusing to serve files larger than N bytes by default.
|
|
55
|
+
- Auto-disabling listings on "too many" entries.
|
|
56
|
+
- Forcing small-default pagination on the listing UI.
|
|
57
|
+
|
|
58
|
+
When proposing a new feature, ask: *"does this change the default observable behavior of `GET /path/to/file` or `GET /some/dir/`?"* If yes, it is a restriction — make it opt-in.
|
|
59
|
+
|
|
60
|
+
> Note: `method: ['GET']` IS technically restrictive (rejects HEAD, POST, etc. by default). It is kept as-is because it has been the v2 default since forever and the migration cost is not worth the philosophical purity. Documented as a known imperfection.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Consequences for future changes
|
|
65
|
+
|
|
66
|
+
- **New options should default to "transparent / pass-through".** A new feature that changes default observable behavior must be defended in the PR description: why is this a safety net and not a restriction?
|
|
67
|
+
|
|
68
|
+
- **Security hardening lives in documentation, not in defaults.** When you find a hardening opportunity, the first instinct should be to add a row to the *Security Checklist* in `README.md` and `docs/DOCUMENTATION.md`, not to change a default. Defaults serve operators; the checklist guides them when they need to harden.
|
|
69
|
+
|
|
70
|
+
- **Breaking-change cost is real.** This middleware has v2-era stable options. Renaming or changing default behavior of stable options breaks every operator on upgrade. Justify breaks by **structural necessity**, not by aesthetic preference. Renaming `showDirContents` → `dirListing.enabled` was justified because it was needed to group related listing options under a namespace. Renaming `hideExtension.redirect` → `redirectStatusCode` would be aesthetic only and was therefore declined.
|
|
71
|
+
|
|
72
|
+
- **Aliases for v2-stable names are acceptable** to soften transitions, with a one-time deprecation warning via `_logger.warn(...)` (see the `showDirContents` alias for the canonical pattern).
|
|
73
|
+
|
|
74
|
+
- **Throw guards for V3-alpha-only options** are acceptable as hard breaks (no v2 user has them; alpha-testers accept breakage).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Key references
|
|
79
|
+
|
|
80
|
+
- **`README.md`** — user-facing entry point. Contains Security Checklist and Suggested Security Configuration sections.
|
|
81
|
+
- **`docs/DOCUMENTATION.md`** — full API reference and Best Practices guide.
|
|
82
|
+
- **`docs/CHANGELOG.md`** — version history; breaking changes documented under *⚠️ Breaking Changes*.
|
|
83
|
+
- **`docs/security_improvement_for_V3.md`** — audit roadmap for v3 security improvements (implemented + Future Work under `[F-1]`).
|
|
84
|
+
- **`__tests__/`** — 543+ tests asserting behavior contracts. Run with `npm test`.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Working conventions
|
|
89
|
+
|
|
90
|
+
- All defaults are documented in the JSDoc-style block at the top of the factory function in `index.cjs` (~line 480). When you change a default, update that block.
|
|
91
|
+
- Validation errors throw at factory time with a helpful migration hint. See existing throw guards for `cacheMaxAge`, `enableCaching`, `maxDirEntries`, `pageSize`, `compression.minSize`.
|
|
92
|
+
- Tests use `supertest` over a `Koa` app instantiated per `describe` block.
|
|
93
|
+
- The CSP hash for the directory-listing inline CSS is computed once at module load (`_listingCssHash`) — editing the listing CSS automatically refreshes the hash. Tests that asserted the hash must compute it from the actual `<style>` block in the response, not hardcode it.
|
|
94
|
+
- Once-per-process warnings use a module-level boolean flag (see `_showDirContentsDeprecationWarned` for the canonical pattern).
|
|
95
|
+
- Logger calls use `warnPayload(_logger, msg)` so that structured loggers (pino/winston) receive plain text and `console` receives ANSI colors.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## When in doubt
|
|
100
|
+
|
|
101
|
+
Re-read the **Design philosophy** section above. If the change you are about to propose would make `GET /some/file` behave differently than the operator placing that file would expect, you are probably violating the philosophy. Either redesign the change as opt-in, or document the rationale explicitly in the PR.
|