I'm working on an API server implemented with the Phoenix Framework. JSON APIs are served from the /api/<version> URL. The server also needs to serve static .html (and others, .css, .js, etc.) files from / : it's actually a little SPA developed in another language and compiled down to HTML5, JS and CSS. The behavior should be:
/should serve theindex.htmlfile;/some/file.htmlshould serve thefile.htmlfile from thesomedirectory provided the path exists and 404 if it doesn't;- URLs like
/some/should send back a 403 or a 404 to prevent directory listing - everything under
/apiis managed by dedicated controllers.
The project is generated with mix phx.new --no-ecto --no-html --no-gettext --no-webpack static to get rid of .css, .js files and of the templates. I also created a priv/static directory for the statics assets.
I had to remove only: ~w(css fonts images js favicon.ico robots.txt) from the parameter list of plug Plug.Static in endpoint.ex to have files at the root URL being served. All works fine except the errors:
- a request on
/displays the Phoenix error page with the log[debug] ** (Phoenix.Router.NoRouteError) no route found for GET / (StaticWeb.Router). I added{:plug_static_index_html, "~> 1.0"}so I got rid of that problem, yet invoking/subdirsends back Phoenix error page. I just don't see where and how to tell Phoenix to send back a 403 or a 404 (except for/). - Invoking a URL on a non-exiting file does not send back a 404 but rather the Phoenix error page. I tried to create a
staticpipeline inrouter.exbut it seems the flow doesn't get there. The documentation states: If a static asset cannot be found,Plug.Staticsimply forwards the connection to the rest of the pipeline. but I don't see where to put the 404 reply.
Here are the two configurations I tried:
Conf I
# endpoint.ex
...
# Serve at "/" the static files from "priv/static" directory.
plug Plug.Static.IndexHtml, at: "/"
plug Plug.Static,
at: "/",
from: :static,
gzip: false
# only: ~w(css fonts images js favicon.ico robots.txt)
...
Conf II
I removed every thing concerning static content from endpoint.ex and added a static pipeline in router.ex
# router.ex
...
pipeline :static do
plug :put_secure_browser_headers
plug Plug.Static,
at: "/",
from: :static,
gzip: false # ,
# only: ~w(css fonts images js favicon.ico robots.txt)
plug :not_found
end
scope "/", staticWeb do
pipe_through :static
end
def not_found(conn, _) do
send_resp(conn, 404, "not found")
end
...
Any hint would be helpful.
Update on 13th of August 2020
Added a catch all rule on scope "/" at the end of router.ex and at least I get a 404 for any wrong request. I'm just wondering how clean all this is...
# router.ex
...
scope "/", AlaaarmWeb do
match :*, "/*path", DefController, :error_404
end