Skip to content

Match whole segments for statics in verified routes - #6896

Open
mandar1045 wants to merge 4 commits into
phoenixframework:mainfrom
mandar1045:fix-statics-segment-match
Open

mandar1045 wants to merge 4 commits into
phoenixframework:mainfrom
mandar1045:fix-statics-segment-match

Conversation

@mandar1045

Copy link
Copy Markdown

Closes #6895.

static_path?/2 used String.starts_with?, so with the default statics a route
like ~p"/images-gallery" was treated as a static file. It wasn't verified, url/1
pointed it to the static host, and path prefixes were skipped.

Now the whole first segment has to match, same as Plug.Static's :only. Paths
like /images/logo.png and /favicon.ico are still static.

Added tests for the prefix/url case and for the missing warning.

@rhcarvalho rhcarvalho left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I agree the current behavior is surprising when the matching is not segment-aware.

Not sure about breaking current behavior for any apps that might have a multi-segment path in :statics.

Comment thread lib/phoenix/verified_routes.ex Outdated
# Like Plug.Static's :only, the whole first segment must match
defp static_path?(path, statics) do
Enum.find(statics, &String.starts_with?(path, "/" <> &1))
[_, segment | _] = String.split(path, ["/", "#"], parts: 3)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Currently https://phoenix.hexdocs.pm/Phoenix.VerifiedRoutes.html#module-options doesn't saying anything about depth, only:

:statics - Optional list of static directories to treat as verified paths

Before, statics: ~w(assets/images) would work (accidentally or not), but with this change it doesn't.

Comment thread lib/phoenix/verified_routes.ex Outdated
Comment on lines 1080 to 1083
defp static_path?(path, statics) do
Enum.find(statics, &String.starts_with?(path, "/" <> &1))
[_, segment | _] = String.split(path, ["/", "#"], parts: 3)
segment in statics
end

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We might start from the assumption that a valid path starts with /, and thus split it in at most 2 parts instead of 3 (ignoring the first part):

Suggested change
defp static_path?(path, statics) do
Enum.find(statics, &String.starts_with?(path, "/" <> &1))
[_, segment | _] = String.split(path, ["/", "#"], parts: 3)
segment in statics
end
defp static_path?("/" <> rest, statics) do
[segment | _] = String.split(rest, ["/", "#"], parts: 2)
segment in statics
end

@rhcarvalho
rhcarvalho requested a review from SteffenDE November 3, 2026 16:06
@mandar1045

Copy link
Copy Markdown
Author

@rhcarvalho got it , I missed that. I could match whole segments instead, so images still
skips /images-gallery but assets/images keeps working, ill push the changes in a while

@mandar1045

Copy link
Copy Markdown
Author

It now matches whole segments, so assets/images works like before and
images still doesn't catch /images-gallery. Used your "/" <> rest suggestion
too, and added a test for the multi-segment case.

@mandar1045
mandar1045 requested a review from rhcarvalho November 3, 2026 18:02
Comment thread lib/phoenix/verified_routes.ex Resolved
@mandar1045
mandar1045 requested a review from SteffenDE November 4, 2026 15:27
Comment thread CHANGELOG.md Resolved
@SteffenDE
SteffenDE requested a review from josevalim November 4, 2026 15:49

This branch has not been deployed

No deployments
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.

~p treats routes as static when they only start with a static directory name

3 participants