Phoenix server is delivering default HTML instead of requested JS files

cache
phoenix
javascript
digest

#1

Hi all

I’m pretty new to Elixir/Phoenix so hopefully this isn’t a noob mistake…

I am currently seeing an issue with (I think) the cache manifest whereby my site delivers HTML and CSS files properly but for JS files, the default HTML template is being delivered - which results in an error like:

Refused to execute script from 'http://example.com:4000/js/MyApp.prod.app.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

Server console is showing:

[debug] Processing with Mag.PageController.index/2
  Parameters: %{"path" => ["js", "MyApp.prod.app.js"]}
  Pipelines: [:browser]
[info] Sent 200 in 245µs

Which suggests it thinks it has delivered the file - is that correct?

I can see in the Chrome Dev Tools Network tab that the response from this request is the app.html.eex file.

I have confirmed that the file listed as the current version in cache_manifest.json does exist on the server - the CSS files are (seemingly) being delivered in the same way and work fine.

The project was built on OSX, which is where the original phx.digest command was run. I am trying to use it on CentOS - I’m not deploying a full package, merely re-running phx.server on the CentOS box. I also tried running phx.digest on the CentOS box to no avail.

This may not impact anything but I’m running Phoenix inside a Docker container on the CentOS box.

Any help greatly appreciated and please let me know if I can provide any additional information.


#2

For some reason it matches your page controllers index route. Could you please show us the output of mix phx.routes, the actual definitions from the routes.ex file and also in your endpoint.ex the line(s) starting with plug Plug.Static?

I’m not sure yet if this matters, but have you built the application inside of that centos container or on the mac os?

You shouldn’t mix and match modules compiled on different OS and/or arches. Try to always compile your application on a system that is as close as possible to the deploy target.


#3

Thanks for the quick reply!

Output from mix phx.routes:

phoenix_1   |            *    /api/graphiql  Absinthe.Plug.GraphiQL [schema: MyApp.Schema, interface: :simple]
phoenix_1   |            *    /api           Absinthe.Plug [schema: MyApp.Schema]
phoenix_1   | page_path  GET  /*path         MyApp.PageController :index

This is router.ex (I don’t have a routes.ex so guessing that’s what you meant?

defmodule MyApp.UtilityRouter do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/alive" do
    send_resp(conn, 200, "ok")
  end
end

defmodule MyApp.Router do
  use MyApp.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api" do
    pipe_through :api

    if Mix.env === :dev do
      forward "/graphiql", Absinthe.Plug.GraphiQL,
      schema: MyApp.Schema,
      interface: :simple
    end

    forward "/", Absinthe.Plug,
      schema: MyApp.Schema
  end

  scope "/", MyApp do
    pipe_through :browser

    forward "/utility", UtilityRouter

    get("/*path", PageController, :index)
  end
end

endpoint.ex:

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

It’s being built within the container itself (until I get a local build slave to build a full deployment package) as part of the docker-compose like:

mix archive.install phx_1.6.ez --force
mix local.hex --force
mix deps.get --force
mix local.rebar --force
mix phx.digest

Then the docker run command is mix phx.server.


#4

Is plug static before or after your router plug?

What is phx_1.6?

Why are you installing rebar after building your deps? You probably won’t need it anymore by then.


#5

Static is before my router.

phx_1.6 is I believe a poorly named elixir 1.6 install.

It looks like that may have been left over from something else - I’m going to play the noob card again here…


#6

Installing that archive is very suspicious, especially as you have no clue what it does.

But before digging further into your docker container… Does it work locally when running mix phx.server?


#7

I’ve checked - the archive is Elixir 1.6 - that is Docker’s standard base image.

Nothing is installed on the CentOS box , everything runs through the Docker container. Do you think it would be worth installing Elixir directly on the CentOS box and trying it there? Is that a relevant test?

When I run locally on OSX using mix phx.server, everything runs as expected.


#8

But why are you archive.installing it then?


#9

Looks like some confusion with the guy who put the Docker container together - didn’t realise that deps.get would install Phoenix - that image was Elixir 1.6 with Phoenix.

That line has now been removed.


#10

Are the resources being served correctly without digesting?
As I understood you are trying to serve a SPA from the PageController thus the path /*path will match anything that was not prior matched. If the resources are being served correctly without digesting then you might need to configure the Static plug to handle the folders where the digested files are sent. (I can’t remember if they are the same, I have been months without Elixir)


#11

@joaoevangelista thanks for the suggestion - sent me off down the path of serving static files and came across this thread Static files not found where the OP was referencing files which didn’t actually exist.

My issue was that in app.html.eex I was using MYApp.prod.app.js yet the actual file being produced was MyApp.prod.app.js. OSX is more forgiving than CentOS when it comes to such things.

@NobbZ thanks for your help as well :+1:t3:

Sorry for wasting time! Hopefully this helps someone else in the same scenario, though - even if the filenames seem correct, double, no triple check!