Skip to content

Conversation

Dipali127
Copy link

Summary

This PR makes the root option optional when serve: false in fastifyStatic asynchronous function.
Previously, a dummy directory was required just to satisfy validation.

Changes

  • Updated index.js to skip root validation if serve: false.
  • Added a new test serve-option.test.js to verify behavior with and without serving.

Tests

  • serve: false → no automatic routes are created, sendFile still works.
  • serve: true → normal static file serving works as expected.

Fixes #460

@Fdawgs
Copy link
Member

Fdawgs commented Oct 7, 2025

@Dipali127 The index.js change is missing.

Copy link
Member

@Fdawgs Fdawgs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert the stylistic changes please as they're not needed and are adding noise when reviewing.

@Dipali127
Copy link
Author

@Fdawgs I reverted the stylistic changes as requested.
The PR now only contains the functional change for skipping root validation when serve is false.

@Fdawgs Fdawgs requested a review from Copilot October 10, 2025 08:41
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for making the root option optional when serve: false is specified in fastifyStatic, allowing users to skip providing a dummy directory when they only want to use sendFile functionality.

  • Conditionally skip root validation when serve: false
  • Add comprehensive tests to verify both serving and non-serving behavior

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
index.js Added conditional logic to skip root validation when serve is false
test/serve-option.test.js New test file to verify serve option behavior with and without static file serving
test/root/example.html Test fixture HTML file for serving tests

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Dipali127
Copy link
Author

Hi @Fdawgs, I’ve resolved all the Copilot comments and fixed the lint issues. The PR is now ready for final review and merge. 😊

@Fdawgs Fdawgs requested a review from a team October 14, 2025 07:29
@is2ei
Copy link
Contributor

is2ei commented Oct 14, 2025

@Dipali127

The type should also be updated if the root option can be undefined.
For example:
https://github.com/Dipali127/fastify-static/blob/serve-false-root-optional/types/index.d.ts#L88

Also, could you please confirm that the issues mentioned in the comment below are resolved by your changes?
#467 (review)

It may fail to serve files because no root is provided. You can see that the root path is passed everywhere in the codebase. You must provide a test to ensure it works correctly.
It could lead to a security issue because, by default, serving files could escape to anywhere. You should at least default the root to the current working directory (CWD) and update the README.

opts.root = normalizeRoot(opts.root)
checkRootPathForErrors(fastify, opts.root)
if (opts.serve !== false) {
opts.root = normalizeRoot(opts.root)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Dipali127
Why should normalizeRoot also be skipped?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this scenario we are not using root if I'm not wrong

@Dipali127
Copy link
Author

Hi @is2ei 👋, thank you for the feedback!

I’ve updated the PR with the following changes and clarifications:

Type update:
I’ve made the root option optional in types/index.d.ts since it’s no longer required when serve: false.
This aligns the type definition with the current logic, where developers can use reply.sendFile() without specifying a root at registration time.

Regarding skipping normalizeRoot():
When serve: false, the plugin does not automatically serve static files.
In this mode, developers are expected to manually call reply.sendFile() — where they can explicitly pass a root if needed.
Therefore, normalizing or validating root at registration time isn’t required.
However, if you prefer that normalizeRoot() should always be called regardless of serve, I can adjust the code to normalize root before the if (opts.serve !== false) condition.

About issue #467:
My PR does not address issue #467 — it specifically focuses on making root optional when serve: false.
The potential serving or security concerns mentioned in #467 aren’t part of the scope of this change.

Let me know your thoughts — I can update the normalizeRoot handling based on your preferred behavior. 😊

@Fdawgs
Copy link
Member

Fdawgs commented Oct 15, 2025

Thanks @Dipali127, could you update the types tests and then i'm happy.

Thanks for taking a look @is2ei.

@Uzlopak
Copy link
Contributor

Uzlopak commented Oct 15, 2025

@Dipali127

Could you please disclose any use of AI usage for this PR?

Copy link
Contributor

@Uzlopak Uzlopak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suspected AI use.

@Fdawgs
Copy link
Member

Fdawgs commented Oct 15, 2025

Suspected AI use.

I though so over here in #537 (comment) as the em-dash is suspect but wanted to give benefit of the doubt.


export interface FastifyStaticOptions extends SendOptions {
root: string | string[] | URL | URL[];
root?: string | string[] | URL | URL[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boring to write, but we need something like:

export interface FastifyStaticOptions extends SendOptions {
  ...stuff
} & ({
  serve: false,
} | {
  serve: true,
  root: string | string[] | URL | URL[];
})

opts.root = normalizeRoot(opts.root)
checkRootPathForErrors(fastify, opts.root)
if (opts.serve !== false) {
opts.root = normalizeRoot(opts.root)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this scenario we are not using root if I'm not wrong


t.after(() => fastify.close())
await fastify.listen({ port: 0 })
fastify.server.unref()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fastify.server.unref()
t.after(() => fastify.close())


t.after(() => fastify.close())
await fastify.listen({ port: 0 })
fastify.server.unref()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fastify.server.unref()
t.after(() => fastify.close())

@Uzlopak
Copy link
Contributor

Uzlopak commented Oct 15, 2025

I close this in favor of #540

@Uzlopak Uzlopak closed this Oct 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

When using serve: false, root should be optional

6 participants