fastify-static: inconsistent application of `encodeUri`

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.21.1

Plugin version

4.2.3

Node.js version

14.17.6

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

11.6

Description

I needed to disable the wildcard setup in favor of explicit static routes so I could use the catch all route for handling non-static pages.

This broke some unrelated route handling later on and I’ve tracked it back to this change. I have files that need to be served from the /page-data/app/[...]/page-data.json route. This works fine when wildcard: true. However, when wildcard: false the code uses encodeUri on all the file names meaning the server is now listening for /page-data/app/%5B...%5D/page-data.json and breaks my app.

Steps to Reproduce

Try serving a file with fastify-static and wildcard: false. If the file has characters modified by encodeUri then the file will 404.

Expected Behavior

I’d expect that setting wildcard: false would still allow /page-data/app/[...]/page-data.json to be served at it’s correct path.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 17 (8 by maintainers)

Commits related to this issue

Most upvoted comments

@moonmeister according to rfc the [ and ] characters must always be encoded (stackoverflow). But it looks like browsers (like chrome) and node-fetch just ignore that rule and send [ and ] as is. When you set wildcard: false the framework lists all the files in root directory and creates handlers for each file doing encodeURI for files paths which is the right thing to do. But node-fetch or chrome send un-escaped [ ] so the path does not match to any file. When you set wildcard: true obviously the framework creates a single handler for root + '*' path. Then no matter if browser encodes the path or not it gets to the handler with asterisk. In your case I would suggest to always encode path when requesting the file (which won’t work in browser):

const res = await fetch(encodeURI(`http://localhost:3000${path}`));

Another solution would be to PR the code and add un-encoded (decoded) routes along with encoded ones. But I am not sure how bad this solution is.