Skip to content

Conversation

@dmgawel
Copy link

@dmgawel dmgawel commented Oct 1, 2025

Problem

When using the extensions option, send inconsistently handles path resolution depending on whether a directory exists at the requested path.

For example, given this file structure:

dist/
  about.html
  about/
    team.html
  contact.html

When requesting paths with extensions: ['html'] configured:

  • /contact (no directory exists) → serves contact.html
  • /about (directory exists) → redirects to /about/ instead of serving about.html

This inconsistency occurs because:

  1. When a path doesn't exist, send receives an ENOENT error and tries extensions, successfully serving contact.html
  2. When a path exists as a directory, send immediately calls redirect(path) without trying extensions first
  3. The extension checking logic only runs when the initial stat() returns ENOENT

This behavior is problematic for static site generators and frameworks that want to serve files like about.html from the URL /about (no trailing slash) while also having subdirectories like about/team.html.

Solution

Modified sendFile() to attempt extension resolution before redirecting when:

  • The path resolves to a directory
  • Extensions are configured
  • The path has no file extension
  • The path doesn't end with a separator

The next() function now tracks whether the original path was a directory via an isDir parameter. If all configured extensions fail to
resolve to a file and the original path was a directory, it falls back to the standard directory redirect behavior.

This ensures consistent behavior:

  • /contact with contact.html present → serves contact.html
  • /about with about.html present → serves about.html
  • /about with only about/ directory → redirects to /about/
  • /about with both present → serves about.html (prioritizes file over directory)

References

Resolves #194
Related to expressjs/serve-static#138

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.

Allow falling back to file when directory exists but doesn't have index

1 participant