bug: directory index route root priority is overwritten when wildcard is false
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- javascript, node.js
Research direction
The report points to index.js lines 206–209 and describes a reproduction with two root directories and wildcard: false. Read that index route logic and run the reproduction or the relevant existing tests. Done when directory requests keep serving the matching index file from the first root in the configured priority order.
Written by the indexing model from the issue text.
Description
Prerequisites
- I have read the contribution guidelines.
- I have searched for similar issues before opening this one.
Describe the Bug
When wildcard: false and multiple root directories are configured (e.g. root: [root1, root2]), the documentation states that directories are searched in priority order ("first found, first served"):
An array of directories can be provided to serve multiple static directories under a single prefix. Files are served in a "first found, first served" manner, so list directories in order of priority.
However, in index.js lines 206–209:
const key = path.posix.basename(route)
if (indexes.has(key) && !indexDirs.has(key)) {
indexDirs.set(path.posix.dirname(route), rootPath)
}
The condition checks !indexDirs.has(key), where key is the filename (e.g. 'index.html' or 'foobar.html'), but the map entries in indexDirs use directory paths (path.posix.dirname(route)) as keys!
Because the filename string is never a key in indexDirs (which contains directory paths like '/' or '/sub'), !indexDirs.has(key) always evaluates to true whenever an index file is found in subsequent roots with a different alternative index name or secondary root. As a result, subsequent lower-priority roots overwrite higher-priority roots in indexDirs.set(path.posix.dirname(route), rootPath), causing directory requests (e.g. / or /<dir>/) to serve from the wrong root!
Steps to Reproduce
const Fastify = require('fastify')
const fastifyStatic = require('@fastify/static')
const path = require('node:path')
const fs = require('node:fs')
// Setup two roots: root1 (high priority) and root2 (lower priority)
const root1 = path.join(__dirname, 'root1')
const root2 = path.join(__dirname, 'root2')
fs.mkdirSync(path.join(root1, 'sub'), { recursive: true })
fs.mkdirSync(path.join(root2, 'sub'), { recursive: true })
fs.writeFileSync(path.join(root1, 'sub', 'index.htm'), 'from root1')
fs.writeFileSync(path.join(root2, 'sub', 'index.html'), 'from root2')
const fastify = Fastify()
fastify.register(fastifyStatic, {
root: [root1, root2],
wildcard: false,
index: ['index.htm', 'index.html']
})
await fastify.listen({ port: 0 })
const port = fastify.server.address().port
const res = await fetch(`http://localhost:${port}/sub/`)
console.log(await res.text())
// Expected: 'from root1'
// Actual: 'from root2' (lower-priority root overwrote higher-priority root!)
Root Cause
indexDirs is a Map from directory path to rootPath. Line 207 checks whether indexDirs contains key (the basename), rather than checking whether indexDirs already has the directory path path.posix.dirname(route).
Expected Behavior
indexDirs should check whether the directory path already has a registered root (!indexDirs.has(dir)), preserving the higher-priority root.
- Dominant language
- JavaScript
- Stars
- 499
- Forks
- 131
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 1
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from fastify/fastify-static
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
fastify/fastify-static#612 · 1 comment ·
-
10.1.4 regression: path spelling validation calls readdir() on every request, O(n) latency for large directoriesPossibly taken @mcollina claimed this 17 days ago. Open
Difficulty 4/5 3-5 days Newbie friendliness 52/100
fastify/fastify-static#613 ·
-
Use built-in glob from `node:fs`Possibly taken @Ankitraj-sharma claimed this 13 days ago. Opengood first issue
Difficulty 3/5 1-2 days Newbie friendliness 25/100
fastify/fastify-static#551 · 8 comments · 1 reaction ·
-
feature request
Difficulty 5/5 Over a week Newbie friendliness 25/100
fastify/fastify-static#432 · 2 comments ·
-
discussion
Difficulty 5/5 Over a week Newbie friendliness 25/100
fastify/fastify-static#385 · 2 comments ·
All issues in fastify/fastify-static
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
microsoft/playwright#43327 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
microsoft/TypeScript#64758 ·
Maintainers usually reply within 1 day
-
needs-area-label
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 65/100
-
bug good first issue help wanted status: planned
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
andersthemagi/reliquary#310 ·
Maintainers usually reply within 1 day