58 lines
1.5 KiB
Elixir
58 lines
1.5 KiB
Elixir
|
|
defmodule ShootingEventPhxWeb.FrontendController do
|
||
|
|
use ShootingEventPhxWeb, :controller
|
||
|
|
|
||
|
|
def serve(conn, %{"path" => segments}) do
|
||
|
|
request_path =
|
||
|
|
segments
|
||
|
|
|> List.wrap()
|
||
|
|
|> Enum.join("/")
|
||
|
|
|> String.trim_leading("/")
|
||
|
|
|
||
|
|
if String.starts_with?(request_path, "api") do
|
||
|
|
send_resp(conn, 404, "Not Found")
|
||
|
|
else
|
||
|
|
web_dir = web_dir()
|
||
|
|
requested = if request_path == "", do: "index.html", else: request_path
|
||
|
|
requested_file = safe_file_path(web_dir, requested)
|
||
|
|
|
||
|
|
cond do
|
||
|
|
requested_file != nil and File.regular?(requested_file) ->
|
||
|
|
send_static_file(conn, requested_file)
|
||
|
|
|
||
|
|
File.regular?(Path.join(web_dir, "index.html")) ->
|
||
|
|
send_static_file(conn, Path.join(web_dir, "index.html"))
|
||
|
|
|
||
|
|
true ->
|
||
|
|
send_resp(conn, 404, "frontend build not found. run make build")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
defp web_dir do
|
||
|
|
System.get_env("WEB_DIR") || Path.expand("../frontend/dist", File.cwd!())
|
||
|
|
end
|
||
|
|
|
||
|
|
defp safe_file_path(web_dir, request_path) do
|
||
|
|
cleaned = request_path |> Path.expand(web_dir)
|
||
|
|
root = Path.expand(web_dir)
|
||
|
|
|
||
|
|
if String.starts_with?(cleaned, root) do
|
||
|
|
cleaned
|
||
|
|
else
|
||
|
|
nil
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
defp send_static_file(conn, file_path) do
|
||
|
|
content_type =
|
||
|
|
case MIME.from_path(file_path) do
|
||
|
|
"" -> "application/octet-stream"
|
||
|
|
type -> type
|
||
|
|
end
|
||
|
|
|
||
|
|
conn
|
||
|
|
|> put_resp_content_type(content_type)
|
||
|
|
|> send_file(200, file_path)
|
||
|
|
end
|
||
|
|
end
|