Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ Default: `true`
If set to `true`, `fastify-static` adds a wildcard route to serve files.
If set to `false`, `fastify-static` globs the filesystem for all defined
files in the served folder (`${root}/**/*`), and just creates the routes needed for
those.
If set to a glob `string` pattern, `fastify-static` will use the provided string when globing the filesystem (`${root}/${wildcard}`).
those and it will not serve the newly added file on the filesystem.

The default options of https://www.npmjs.com/package/glob are applied
for getting the file list.
Expand Down
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ async function fastifyStatic (fastify, opts) {
}

if (opts.serve !== false) {
if (opts.wildcard && typeof opts.wildcard !== 'boolean') throw new Error('"wildcard" option must be a boolean')
if (opts.wildcard === undefined || opts.wildcard === true) {
fastify.get(prefix + '*', routeOpts, function (req, reply) {
pumpSendToReply(req, reply, '/' + req.params['*'], sendOptions.root)
Expand All @@ -186,7 +187,7 @@ async function fastifyStatic (fastify, opts) {
})
}
} else {
const globPattern = typeof opts.wildcard === 'string' ? opts.wildcard : '**/*'
const globPattern = '**/*'

async function addGlobRoutes (rootPath) {
const files = await globPromise(path.join(rootPath, globPattern), { nodir: true })
Expand Down
235 changes: 9 additions & 226 deletions test/static.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1661,8 +1661,8 @@ t.test('register with wildcard false', t => {
})
})

t.test('register with wildcard "**/index.html"', t => {
t.plan(8)
t.test('register with wildcard string', t => {
t.plan(1)

const pluginOptions = {
root: path.join(__dirname, '/static'),
Expand All @@ -1675,105 +1675,13 @@ t.test('register with wildcard "**/index.html"', t => {
reply.send({ hello: 'world' })
})

t.tearDown(fastify.close.bind(fastify))

fastify.listen(0, err => {
t.error(err)

fastify.server.unref()

t.test('/index.html', t => {
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/index.html'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), indexContent)
genericResponseChecks(t, response)
})
})

t.test('/index.css', t => {
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/index.css'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
genericErrorResponseChecks(t, response)
})
})

t.test('/', t => {
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), indexContent)
genericResponseChecks(t, response)
})
})

t.test('/not-defined', t => {
t.plan(3)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/not-defined'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})

t.test('/deep/path/for/test/purpose/foo.html', t => {
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/purpose/foo.html'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
genericErrorResponseChecks(t, response)
})
})

t.test('/deep/path/for/test/', t => {
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), innerIndex)
genericResponseChecks(t, response)
})
})

t.test('/../index.js', t => {
t.plan(3)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/../index.js',
followRedirect: false
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
fastify.ready(function (err) {
t.ok(err)
})
})

t.test('register with wildcard "**/index.html" on multiple root paths', t => {
t.plan(2)
t.test('register with wildcard string on multiple root paths', t => {
t.plan(1)

const pluginOptions = {
root: [path.join(__dirname, '/static'), path.join(__dirname, '/static2')],
Expand All @@ -1789,134 +1697,9 @@ t.test('register with wildcard "**/index.html" on multiple root paths', t => {
t.tearDown(fastify.close.bind(fastify))

fastify.listen(0, err => {
t.error(err)

fastify.server.unref()

t.test('/index.html', t => {
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/index.html'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
genericErrorResponseChecks(t, response)
})
})
})
})

t.test('register with wildcard "**/foo.*"', t => {
t.plan(8)

const pluginOptions = {
root: path.join(__dirname, '/static'),
wildcard: '**/foo.*'
}
const fastify = Fastify()
fastify.register(fastifyStatic, pluginOptions)

fastify.get('/*', (request, reply) => {
reply.send({ hello: 'world' })
})

t.tearDown(fastify.close.bind(fastify))

fastify.listen(0, err => {
t.error(err)
t.ok(err)

fastify.server.unref()

t.test('/index.html', t => {
t.plan(3 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/index.html'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })

genericErrorResponseChecks(t, response)
})
})

t.test('/index.css', t => {
t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/index.css'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
genericErrorResponseChecks(t, response)
})
})

t.test('/', t => {
t.plan(3 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
genericErrorResponseChecks(t, response)
})
})

t.test('/not-defined', t => {
t.plan(3)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/not-defined'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})

t.test('/deep/path/for/test/purpose/foo.html', t => {
t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/purpose/foo.html'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.strictEqual(body.toString(), deepContent)
genericResponseChecks(t, response)
})
})

t.test('/deep/path/for/test/', t => {
t.plan(3 + GENERIC_ERROR_RESPONSE_CHECK_COUNT)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/'
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
genericErrorResponseChecks(t, response)
})
})

t.test('/../index.js', t => {
t.plan(3)
simple.concat({
method: 'GET',
url: 'http://localhost:' + fastify.server.address().port + '/../index.js',
followRedirect: false
}, (err, response, body) => {
t.error(err)
t.strictEqual(response.statusCode, 200)
t.deepEqual(JSON.parse(body), { hello: 'world' })
})
})
})
})

Expand Down Expand Up @@ -2561,7 +2344,7 @@ t.test('register with failing glob handler', t => {
const pluginOptions = {
root: path.join(__dirname, '/static'),
serve: true,
wildcard: '*'
wildcard: false
}
const fastify = Fastify()
fastify.register(fastifyStatic, pluginOptions)
Expand All @@ -2586,7 +2369,7 @@ t.test('register with rootpath that causes statSync to fail with non-ENOENT code

const pluginOptions = {
root: path.join(__dirname, '/static'),
wildcard: '*'
wildcard: true
}
const fastify = Fastify()
fastify.register(fastifyStatic, pluginOptions)
Expand Down