phoenixframework / phoenix

Peace of mind from prototype to production
https://www.phoenixframework.org
MIT License
21.44k stars 2.87k forks source link

Splat route vs Plug.Static problem? #1036

Closed tmjoen closed 9 years ago

tmjoen commented 9 years ago

In my app, I serve a priv/media directory through an additional Plug.Static in my endpoint.ex

  plug Plug.Static,
    at: "/media", from: "priv/media"

This works fine.

However, when I add a splat route like this:

  # router.ex

    get "/:language/instagram", Neva.InstagramController, :index
    get "/:language/*key", Neva.PageController, :show

I start seeing some weird behaviour with my /media resources. Sometimes/randomly some of the images refuse to load, trying to go the splat route (PageController :show) instead of being handled by the Plug.Static for /media.

When I right click the failed image, and try to reload it in a new tab - it works. The image is there, it just takes a wrong route trying to find it!

If I change the splat route so there are no chances of confusion:

   # router.ex

    get "/n/:language/instagram", Neva.InstagramController, :index
    get "/n/:language/*key", Neva.PageController, :show

It works fine again. Sometimes I don't see this bug for days, then suddenly it shows up all the time.

I realize this is almost impossible to debug, but I thought I'd raise an issue here and see if anything jumped to your minds.

josevalim commented 9 years ago

@tmjoen can you include Phoenix and Plug versions? Have you tried the latest?

josevalim commented 9 years ago

Btw, the description doesn't make much sense because defining a splat route does not change Plug.Static behaviour. Plug.Static is called very early on. What could be happening is just that we are being unable to find to find the static assets for some reason, maybe a file system issue, and that ends up invoking the splat route. They should not be related though.

josevalim commented 9 years ago

Also is this happening in both development and production environment? Or just one? The more information you can give, the best for us to reproduce it, otherwise we won't be able to do much.

tmjoen commented 9 years ago

I see what you mean by the description. I (mistakenly) thought it seemed like a race condition between the router and the static plug, is all.

Version info:

"phoenix": {:hex, :phoenix, "0.14.0"},
"plug": {:hex, :plug, "0.13.0"},

I'll try to reproduce on prod - sometimes it takes a lot of time before I can reproduce :)

josevalim commented 9 years ago

Also, are the media always in priv/media or are they being copied by something? If the media is being generated dynamically, there you are just trying to serve it when something deleted it and is copying it over again.

tmjoen commented 9 years ago

I store uploaded images there. They are not touched once copied there, so the files were there when Plug.Static tried to access them. This is on my dev machine, so I'm the one uploading & checking that the files are in place before trying to load the page.

tmjoen commented 9 years ago

I set up an automatic reloader on two different machines just refreshing the same page over and over and the error turns up randomly.

Then I inspected the path in Plug.Static

it is relative for my media/ Plug.Static:

"priv/media/images/instagram/large/11379309_784422001656659_909160896_n.jpg"

while it is absolute for my static/ Plug.Static

"/Users/tmjoen/dev/elixir/neva/_build/dev/lib/neva/priv/static/fonts/bootstrap/glyphicons-halflings-regular.woff2"

If I change my Plug.Static setup to

  plug Plug.Static,
    at: "/media", from: {:neva, "priv/media"}

my media also has absolute paths and the problem seems to go away. So I guess there's some weird stuff going on with relative paths there?

josevalim commented 9 years ago

Yes, please use absolute paths. IF you use relative paths, someone can decide to change directory (for example, mix while it is compiling) and it is def. going to mess up your lookup, specially if you have path dependencies.

tmjoen commented 9 years ago

Thanks for the help, José!