diff --git a/README.md b/README.md index 6b373a95..634a0880 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,14 @@ are applied for getting the file list. This option cannot be `false` if `redirect` is `true` and `ignoreTrailingSlash` is `true`. +#### `globIgnore` + +Default: `undefined` + +This is passed to [`glob`](https://www.npmjs.com/package/glob) +as the `ignore` option. It can be used to ignore files or directories +when using the `wildcard: false` option. + #### `allowedPath` Default: `(pathName, root, request) => true` diff --git a/index.js b/index.js index 08e70b4d..e6521159 100644 --- a/index.js +++ b/index.js @@ -135,7 +135,7 @@ async function fastifyStatic (fastify, opts) { rootPath = rootPath.split(path.win32.sep).join(path.posix.sep) !rootPath.endsWith('/') && (rootPath += '/') const files = await glob('**/**', { - cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles + cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles, ignore: opts.globIgnore }) for (let file of files) { diff --git a/test/static-filtered/bar.private b/test/static-filtered/bar.private new file mode 100644 index 00000000..5716ca59 --- /dev/null +++ b/test/static-filtered/bar.private @@ -0,0 +1 @@ +bar diff --git a/test/static-filtered/deep/path/to/baz.html b/test/static-filtered/deep/path/to/baz.html new file mode 100644 index 00000000..bd2a31ff --- /dev/null +++ b/test/static-filtered/deep/path/to/baz.html @@ -0,0 +1,3 @@ + + baz + diff --git a/test/static-filtered/deep/path/to/baz.private b/test/static-filtered/deep/path/to/baz.private new file mode 100644 index 00000000..76018072 --- /dev/null +++ b/test/static-filtered/deep/path/to/baz.private @@ -0,0 +1 @@ +baz diff --git a/test/static-filtered/index.html b/test/static-filtered/index.html new file mode 100644 index 00000000..e3b8da08 --- /dev/null +++ b/test/static-filtered/index.html @@ -0,0 +1,3 @@ + + index2 + diff --git a/test/static.test.js b/test/static.test.js index dba7a90d..1502016c 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -3669,3 +3669,77 @@ test('register /static/ with custom log level', async t => { t.assert.deepStrictEqual(response2.status, 304) }) }) + +test('register with wildcard false and globIgnore', async t => { + t.plan(5) + + const indexContent = fs + .readFileSync('./test/static-filtered/index.html') + .toString('utf8') + + const deepContent = fs + .readFileSync('./test/static-filtered/deep/path/to/baz.html') + .toString('utf8') + + const pluginOptions = { + root: path.join(__dirname, '/static-filtered'), + wildcard: false, + globIgnore: ['**/*.private'] + } + const fastify = Fastify() + fastify.register(fastifyStatic, pluginOptions) + + t.after(() => fastify.close()) + + await fastify.listen({ port: 0 }) + + fastify.server.unref() + + await t.test('/index.html', async t => { + t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) + + const response = await fetch('http://localhost:' + fastify.server.address().port + '/index.html') + t.assert.ok(response.ok) + t.assert.deepStrictEqual(response.status, 200) + t.assert.deepStrictEqual(await response.text(), indexContent) + genericResponseChecks(t, response) + }) + + await t.test('/bar.private', async t => { + t.plan(2) + + const response = await fetch('http://localhost:' + fastify.server.address().port + '/bar.private') + t.assert.ok(!response.ok) + t.assert.deepStrictEqual(response.status, 404) + await response.text() + }) + + await t.test('/', async (t) => { + t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) + + const response = await fetch('http://localhost:' + fastify.server.address().port) + t.assert.ok(response.ok) + t.assert.deepStrictEqual(response.status, 200) + t.assert.deepStrictEqual(await response.text(), indexContent) + genericResponseChecks(t, response) + }) + + await t.test('/deep/path/to/baz.html', async (t) => { + t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) + + const response = await fetch('http://localhost:' + fastify.server.address().port + '/deep/path/to/baz.html') + t.assert.ok(response.ok) + t.assert.deepStrictEqual(response.status, 200) + t.assert.deepStrictEqual(await response.text(), deepContent) + genericResponseChecks(t, response) + }) + + await t.test('/deep/path/to/baz.private', async (t) => { + t.plan(2) + + const response = await fetch('http://localhost:' + fastify.server.address().port + '/deep/path/to/baz.private') + t.assert.ok(!response.ok) + t.assert.deepStrictEqual(response.status, 404) + await response.text() + }) +}) diff --git a/types/index.d.ts b/types/index.d.ts index 1f12e40c..d410bb21 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -94,6 +94,7 @@ declare namespace fastifyStatic { setHeaders?: (res: SetHeadersResponse, path: string, stat: Stats) => void; redirect?: boolean; wildcard?: boolean; + globIgnore?: string[]; list?: boolean | ListOptionsJsonFormat | ListOptionsHtmlFormat; allowedPath?: (pathName: string, root: string, request: FastifyRequest) => boolean; /** diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 9be7cb9c..c1936310 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -50,6 +50,7 @@ const options: FastifyStaticOptions = { schemaHide: true, serve: true, wildcard: true, + globIgnore: ['**/*.private'], list: false, setHeaders: (res, path, stat) => { expectType(res.filename)