Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for files with % in filename #452

Merged
merged 4 commits into from May 7, 2024

Conversation

chetbox
Copy link
Contributor

@chetbox chetbox commented May 2, 2024

Resolves #451

  • Fix 400 Bad Request error when serving files with a % in the filename
  • Correctly URI-encode href parameter for directory listings (otherwise files with a % in the filename generate an invalid href)

Checklist

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@@ -221,7 +221,8 @@ async function fastifyStatic (fastify, opts) {
}
}

const stream = send(request.raw, pathnameForSend, options)
// `send(..., path, ...)` will URI-decode path so we pass an encoded path here
const stream = send(request.raw, encodeURI(pathnameForSend), options)
Copy link
Contributor

Choose a reason for hiding this comment

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

your comment: we uri decode path in send? How about apply a change in @fastify/send , like pass decodeUri option in options, by default true for backwards compat and we set it here to false and then we dont need to encodeURI?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the docs of @fastify/send is seems the path passed is intended to be URL-encoded:

path is a urlencoded path to send (urlencoded, not the actual file-system path)

https://github.com/fastify/send?tab=readme-ov-file#api

While I agree that this seems like a little extra overhead it looks like the @fastify/send API was not being used correctly.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe send could be refactored to do what Uzlopak suggests

@@ -149,7 +149,7 @@ const dirList = {
route = path.normalize(path.join(route, '..'))
}
return {
href: path.join(prefix, route, entry.name).replace(/\\/gu, '/'),
href: encodeURI(path.join(prefix, route, entry.name).replace(/\\/gu, '/')),
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder, can we avoid this regex?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This regex was already there. I tried switching to path.posix.join but that failed the tests on Windows.

@@ -149,7 +149,7 @@ const dirList = {
route = path.normalize(path.join(route, '..'))
Copy link
Contributor

@Uzlopak Uzlopak May 2, 2024

Choose a reason for hiding this comment

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

What if we change it to?

Maybe on top of the file we do:
const pathPosixNormalize = path.posix.normalize
and then do:

Suggested change
route = path.normalize(path.join(route, '..'))
route = pathPosixNormalize(path.join(route, '..'))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might work but it's not part of the fix for this PR. See #452 (comment)

@Uzlopak
Copy link
Contributor

Uzlopak commented May 2, 2024

I have the feeling, that we would reduce the performance with this change, and with a little bit more effort we can improve the overall performance. wdyt?

@chetbox
Copy link
Contributor Author

chetbox commented May 2, 2024

I have the feeling, that we would reduce the performance with this change, and with a little bit more effort we can improve the overall performance. wdyt?

In my opinion the slight performance hit is worth it for the correctness. It's worth noting that encodeURI is a native function and very fast so in the context of an HTTP response is negligible. (On my machine - M1 MacBook Pro - encodeURI while running the test suites averages ~0.001 milliseconds.)

@mcollina
Copy link
Member

mcollina commented May 3, 2024

@Uzlopak the performance of this module is already pretty bad. We can't even try to match NGINX and similar in hosting static files. I don't think adding this is a problem.

@gurgunday
Copy link
Member

@mcollina would fastify/send#15 improve performance?

@chetbox
Copy link
Contributor Author

chetbox commented May 7, 2024

To be honest, I think performance is not much of a consideration here and is a little off-topic. This change is about fixing a behaviour that is clearly a bug.

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.

LGTM

I benchmarked and did not see a significant performance loss.

@Uzlopak Uzlopak merged commit 0f6af4e into fastify:master May 7, 2024
17 checks passed
@chetbox chetbox deleted the percent-in-filename branch May 7, 2024 14:40
@chetbox
Copy link
Contributor Author

chetbox commented May 7, 2024

Thanks all! 🙏🏼 When do you expect this to be in a release?

@gurgunday
Copy link
Member

Just released v7.0.4

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.

400 Bad Request for files containing a % character
4 participants