5

I want to set Phoenix up to serve a static index.html no matter what route is sent to it, without changing the URL and while providing access to non-html assets (.js, .css, .jpg,...), as my SPA (in Elm) will look at the route and work out what to do.

Based on this and this I have tried the following, but without success

endpoint.ex

  plug Plug.Static,
    at: "/", from: :mosaic_api, gzip: false,
    only: ~w(assets css fonts images js favicon.ico robots.txt index.html)

router.ex

  scope "/", Api do
    pipe_through :browser # Use the default browser stack
    get "/*path", PageController, :index  # :elm
  end

PageController.ex

defmodule Api.PageController do
  use Api.Web, :controller

  plug :action  # Edit: now removed

  def index(conn, _params) do
    conn
    |> put_layout(false)
    |> render("index.html")
    # Edit: replaced 3 lines above by: html(conn, File.read!("priv/static/index.html"))
  end

  def elm(conn, _params) do
      redirect conn, to: "/index.html"
  end
end

With :index I get a Phoenix-related (but not the standard home-) page and a console error (Plug.Conn.AlreadySentError) the response was already sent, while with :elm I end up at /index.html and have lost the routing information.

Community
  • 1
  • 1
Simon H
  • 20,332
  • 14
  • 71
  • 128

1 Answers1

3
only: ~w(... index.html)

conn
|> put_layout(false)
|> render("index.html")

It seems you try to render the static index.html that's not work. The put_layout/2 disable or change the wrapper layout. render/2 set the file to use as content. Default this file located at /web/templates/MODULE/.

You can use the Phoenix.Controller.html/2 function for send custom html content. Read the the file with File.read!/2 and send the content to the client.

def index(conn, _params) do
  html(conn, File.read!("priv/static/index.html"))
end

I'm not sure if there an other cleaner solution but this should work. Hope this helps.

EDIT:

Solve the AlreadySentError by remove the plug :action from your controller. It is called automatically since version 0.14.0.

See these 0.13.x to 0.14.0 upgrade instructions to bring your existing apps up to speed.

  • Backward incompatible changes
    • [Controller] plug :action is now called automatically
Fabi755
  • 1,495
  • 1
  • 12
  • 29
  • That's helped, but now I am getting errors on all the other static assets about response having been sent before. How can I stop phoenix going further when a static asset is requested? – Simon H Jun 01 '16 at 13:40
  • Remove the `plug :action` from your controller. – Fabi755 Jun 01 '16 at 13:54
  • Sorry, my english isn't very good. I don't understand your current problem, which requirement is not working? In my case there are all statics assets are available (like images, css files and so on) and the html file is the content of all other requested URLs. – Fabi755 Jun 02 '16 at 15:30