Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 39 additions & 41 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,20 @@ async function fastifyStatic (fastify, opts) {
})

stream.on('error', function (err) {
if (err) {
if (err.code === 'ENOENT') {
// if file exists, send real file, otherwise send dir list if name match
if (opts.list && dirList.handle(pathname, opts.list)) {
return dirList.send({ reply, dir: dirList.path(opts.root, pathname), options: opts.list, route: pathname })
}

// root paths left to try?
if (Array.isArray(rootPath) && rootPathOffset < (rootPath.length - 1)) {
return pumpSendToReply(request, reply, pathname, rootPath, rootPathOffset + 1)
}
if (err.code === 'ENOENT') {
// if file exists, send real file, otherwise send dir list if name match
if (opts.list && dirList.handle(pathname, opts.list)) {
return dirList.send({ reply, dir: dirList.path(opts.root, pathname), options: opts.list, route: pathname })
}

return reply.callNotFound()
// root paths left to try?
if (Array.isArray(rootPath) && rootPathOffset < (rootPath.length - 1)) {
return pumpSendToReply(request, reply, pathname, rootPath, rootPathOffset + 1)
}
reply.send(err)

return reply.callNotFound()
}
reply.send(err)
})

// we cannot use pump, because send error
Expand Down Expand Up @@ -199,15 +197,20 @@ async function fastifyStatic (fastify, opts) {
}
} else {
const globPattern = '**/*'
const indexDirs = new Map()
const routes = new Set()

async function addGlobRoutes (rootPath) {
for (const rootPath of Array.isArray(sendOptions.root) ? sendOptions.root : [sendOptions.root]) {
const files = await globPromise(path.join(rootPath, globPattern), { nodir: true })
const indexDirs = new Set()
const indexes = typeof opts.index === 'undefined' ? ['index.html'] : [].concat(opts.index || [])
const indexes = typeof opts.index === 'undefined' ? ['index.html'] : [].concat(opts.index)

for (let file of files) {
file = file.replace(rootPath.replace(/\\/g, '/'), '').replace(/^\//, '')
const route = encodeURI(prefix + file).replace(/\/\//g, '/')
if (routes.has(route)) {
continue
}
routes.add(route)
fastify.head(route, routeOpts, function (req, reply) {
pumpSendToReply(req, reply, '/' + file, rootPath)
})
Expand All @@ -216,38 +219,33 @@ async function fastifyStatic (fastify, opts) {
pumpSendToReply(req, reply, '/' + file, rootPath)
})

if (indexes.includes(path.posix.basename(route))) {
indexDirs.add(path.posix.dirname(route))
const key = path.posix.basename(route)
if (indexes.includes(key) && !indexDirs.has(key)) {
indexDirs.set(path.posix.dirname(route), rootPath)
}
}
}

indexDirs.forEach(function (dirname) {
const pathname = dirname + (dirname.endsWith('/') ? '' : '/')
const file = '/' + pathname.replace(prefix, '')

fastify.head(pathname, routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file, rootPath)
})
for (const [dirname, rootPath] of indexDirs.entries()) {
const pathname = dirname + (dirname.endsWith('/') ? '' : '/')
const file = '/' + pathname.replace(prefix, '')

fastify.get(pathname, routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file, rootPath)
})
fastify.head(pathname, routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file, rootPath)
})

if (opts.redirect === true) {
fastify.head(pathname.replace(/\/$/, ''), routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file.replace(/\/$/, ''), rootPath)
})
fastify.get(pathname.replace(/\/$/, ''), routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file.replace(/\/$/, ''), rootPath)
})
}
fastify.get(pathname, routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file, rootPath)
})
}

if (Array.isArray(sendOptions.root)) {
await Promise.all(sendOptions.root.map(addGlobRoutes))
} else {
await addGlobRoutes(sendOptions.root)
if (opts.redirect === true) {
fastify.head(pathname.replace(/\/$/, ''), routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file.replace(/\/$/, ''), rootPath)
})
fastify.get(pathname.replace(/\/$/, ''), routeOpts, function (req, reply) {
pumpSendToReply(req, reply, file.replace(/\/$/, ''), rootPath)
})
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"simple-get": "^4.0.0",
"snazzy": "^9.0.0",
"standard": "^16.0.2",
"tap": "^14.10.8",
"tap": "^15.0.0",
"tsd": "^0.14.0",
"typescript": "^4.0.2"
},
Expand Down
34 changes: 17 additions & 17 deletions test/dir-list.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const helper = {
arrange: function (t, options, f) {
const fastify = Fastify()
fastify.register(fastifyStatic, options)
t.tearDown(fastify.close.bind(fastify))
t.teardown(fastify.close.bind(fastify))
fastify.listen(0, err => {
t.error(err)
fastify.server.unref()
Expand Down Expand Up @@ -92,8 +92,8 @@ t.test('dir list default options', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), JSON.stringify(content))
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(content))
})
})
})
Expand All @@ -120,8 +120,8 @@ t.test('dir list, custom options', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), JSON.stringify(content))
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(content))
})
})
})
Expand Down Expand Up @@ -228,8 +228,8 @@ t.test('dir list html format', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), template.output)
t.equal(response.statusCode, 200)
t.equal(body.toString(), template.output)
})
})
}
Expand Down Expand Up @@ -262,8 +262,8 @@ t.test('dir list json format', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), JSON.stringify(content))
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(content))
})
})
}
Expand All @@ -289,8 +289,8 @@ t.test('dir list on empty dir', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), JSON.stringify(content))
t.equal(response.statusCode, 200)
t.equal(body.toString(), JSON.stringify(content))
})
})
})
Expand Down Expand Up @@ -321,8 +321,8 @@ t.test('dir list serve index.html on index option', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), '<html>\n <body>\n the body\n </body>\n</html>\n')
t.equal(response.statusCode, 200)
t.equal(body.toString(), '<html>\n <body>\n the body\n </body>\n</html>\n')
})

route = '/public/index'
Expand All @@ -331,8 +331,8 @@ t.test('dir list serve index.html on index option', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), 'dir list index')
t.equal(response.statusCode, 200)
t.equal(body.toString(), 'dir list index')
})
})
})
Expand All @@ -356,7 +356,7 @@ t.test('serve a non existent dir and get error', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 404)
t.equal(response.statusCode, 404)
})
})
})
Expand All @@ -382,7 +382,7 @@ t.test('serve a non existent dir and get error', t => {
url: url + route
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 404)
t.equal(response.statusCode, 404)
})
})
})
Expand Down
Loading