From 34a522cb867b97ea3f904eab0c15a9b39a0d2f7c Mon Sep 17 00:00:00 2001 From: xen143 Date: Tue, 24 Jun 2025 12:39:59 +0200 Subject: [PATCH 1/2] Adding an option to modify the non-existent root directory warning (#524) --- README.md | 6 ++++++ index.js | 16 ++++++++++------ test/static.test.js | 24 ++++++++++++++++++++++++ types/index.d.ts | 1 + 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d1ca01c..321b3e6 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,12 @@ 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. Duplicate paths will raise an error. +#### `getPathNotFoundWarning` + +A custom function that returns a warning message to log when a specified root directory is not found. +It receives a single argument: the path of the missing root directory. +The function should return a string describing the missing path. + #### `prefix` Default: `'/'` diff --git a/index.js b/index.js index e652115..0fb830d 100644 --- a/index.js +++ b/index.js @@ -19,7 +19,7 @@ send.mime.default_type = 'application/octet-stream' async function fastifyStatic (fastify, opts) { opts.root = normalizeRoot(opts.root) - checkRootPathForErrors(fastify, opts.root) + checkRootPathForErrors(fastify, opts.root, opts.getPathNotFoundWarning) const setHeaders = opts.setHeaders if (setHeaders !== undefined && typeof setHeaders !== 'function') { @@ -417,7 +417,7 @@ function normalizeRoot (root) { return root } -function checkRootPathForErrors (fastify, rootPath) { +function checkRootPathForErrors (fastify, rootPath, getPathNotFoundWarning) { if (rootPath === undefined) { throw new Error('"root" option is required') } @@ -434,18 +434,18 @@ function checkRootPathForErrors (fastify, rootPath) { } // check each path and fail at first invalid - rootPath.map((path) => checkPath(fastify, path)) + rootPath.map((path) => checkPath(fastify, path, getPathNotFoundWarning)) return } if (typeof rootPath === 'string') { - return checkPath(fastify, rootPath) + return checkPath(fastify, rootPath, getPathNotFoundWarning) } throw new Error('"root" option must be a string or array of strings') } -function checkPath (fastify, rootPath) { +function checkPath (fastify, rootPath, getPathNotFoundWarning) { if (typeof rootPath !== 'string') { throw new TypeError('"root" option must be a string') } @@ -459,7 +459,11 @@ function checkPath (fastify, rootPath) { pathStat = statSync(rootPath) } catch (e) { if (e.code === 'ENOENT') { - fastify.log.warn(`"root" path "${rootPath}" must exist`) + const warningMessage = + getPathNotFoundWarning + ? getPathNotFoundWarning(rootPath) + : `"root" path "${rootPath}" must exist` + fastify.log.warn(warningMessage) return } diff --git a/test/static.test.js b/test/static.test.js index 1502016..738b600 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -1123,6 +1123,30 @@ test('root not found warning', async (t) => { destination.end() }) +test('custom root not found warning', async (t) => { + t.plan(1) + const rootPath = path.join(__dirname, 'does-not-exist') + const pluginOptions = { + root: rootPath, + getPathNotFoundWarning: (path) => `CUSTOM "root" path "${path}" must exist`, + } + const destination = concat((data) => { + t.assert.deepStrictEqual(JSON.parse(data).msg, `CUSTOM "root" path "${rootPath}" must exist`) + }) + const loggerInstance = pino( + { + level: 'warn' + }, + destination + ) + const fastify = Fastify({ loggerInstance }) + fastify.register(fastifyStatic, pluginOptions) + + await fastify.listen({ port: 0 }) + fastify.server.unref() + destination.end() +}) + test('send options', (t) => { t.plan(12) const pluginOptions = { diff --git a/types/index.d.ts b/types/index.d.ts index d410bb2..59a93b5 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -86,6 +86,7 @@ declare namespace fastifyStatic { export interface FastifyStaticOptions extends SendOptions { root: string | string[] | URL | URL[]; + getPathNotFoundWarning?: (path: string) => string; prefix?: string; prefixAvoidTrailingSlash?: boolean; serve?: boolean; From 5509835f228dab5b206b99fdb986a57c02e3186f Mon Sep 17 00:00:00 2001 From: xen143 Date: Sat, 2 Aug 2025 16:33:50 +0200 Subject: [PATCH 2/2] Adding an option to suppress the non-existent root directory warning --- README.md | 4 ++++ index.js | 13 ++++++++----- test/static.test.js | 24 ++++++++++++++++++++++++ types/index.d.ts | 1 + 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 321b3e6..568dfb2 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,10 @@ A custom function that returns a warning message to log when a specified root di It receives a single argument: the path of the missing root directory. The function should return a string describing the missing path. +#### `suppressPathNotFoundWarning` + +If set to `true`, this option disables the warning message when a specified root directory is not found. + #### `prefix` Default: `'/'` diff --git a/index.js b/index.js index 0fb830d..a1d08a3 100644 --- a/index.js +++ b/index.js @@ -19,7 +19,7 @@ send.mime.default_type = 'application/octet-stream' async function fastifyStatic (fastify, opts) { opts.root = normalizeRoot(opts.root) - checkRootPathForErrors(fastify, opts.root, opts.getPathNotFoundWarning) + checkRootPathForErrors(fastify, opts.root, opts.getPathNotFoundWarning, opts.suppressPathNotFoundWarning) const setHeaders = opts.setHeaders if (setHeaders !== undefined && typeof setHeaders !== 'function') { @@ -417,7 +417,7 @@ function normalizeRoot (root) { return root } -function checkRootPathForErrors (fastify, rootPath, getPathNotFoundWarning) { +function checkRootPathForErrors (fastify, rootPath, getPathNotFoundWarning, suppressPathNotFoundWarning) { if (rootPath === undefined) { throw new Error('"root" option is required') } @@ -434,18 +434,18 @@ function checkRootPathForErrors (fastify, rootPath, getPathNotFoundWarning) { } // check each path and fail at first invalid - rootPath.map((path) => checkPath(fastify, path, getPathNotFoundWarning)) + rootPath.map((path) => checkPath(fastify, path, getPathNotFoundWarning, suppressPathNotFoundWarning)) return } if (typeof rootPath === 'string') { - return checkPath(fastify, rootPath, getPathNotFoundWarning) + return checkPath(fastify, rootPath, getPathNotFoundWarning, suppressPathNotFoundWarning) } throw new Error('"root" option must be a string or array of strings') } -function checkPath (fastify, rootPath, getPathNotFoundWarning) { +function checkPath (fastify, rootPath, getPathNotFoundWarning, suppressPathNotFoundWarning) { if (typeof rootPath !== 'string') { throw new TypeError('"root" option must be a string') } @@ -459,6 +459,9 @@ function checkPath (fastify, rootPath, getPathNotFoundWarning) { pathStat = statSync(rootPath) } catch (e) { if (e.code === 'ENOENT') { + if (suppressPathNotFoundWarning) { + return + } const warningMessage = getPathNotFoundWarning ? getPathNotFoundWarning(rootPath) diff --git a/test/static.test.js b/test/static.test.js index 738b600..1501363 100644 --- a/test/static.test.js +++ b/test/static.test.js @@ -1123,6 +1123,30 @@ test('root not found warning', async (t) => { destination.end() }) +test('suppressing root not found warning', async (t) => { + t.plan(1) + const rootPath = path.join(__dirname, 'does-not-exist') + const pluginOptions = { + root: rootPath, + suppressPathNotFoundWarning: true + } + const destination = concat((data) => { + t.assert.deepStrictEqual(data, []) + }) + const loggerInstance = pino( + { + level: 'warn' + }, + destination + ) + const fastify = Fastify({ loggerInstance }) + fastify.register(fastifyStatic, pluginOptions) + + await fastify.listen({ port: 0 }) + fastify.server.unref() + destination.end() +}) + test('custom root not found warning', async (t) => { t.plan(1) const rootPath = path.join(__dirname, 'does-not-exist') diff --git a/types/index.d.ts b/types/index.d.ts index 59a93b5..8184b6c 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -87,6 +87,7 @@ declare namespace fastifyStatic { export interface FastifyStaticOptions extends SendOptions { root: string | string[] | URL | URL[]; getPathNotFoundWarning?: (path: string) => string; + suppressPathNotFoundWarning?: boolean; prefix?: string; prefixAvoidTrailingSlash?: boolean; serve?: boolean;