Phoenix.Controller.accepts/2 causes a 500 status code in production.
PsionicAlch opened this issue · 2 comments
Environment
- Elixir version (elixir -v): 1.17.1
- Phoenix version (mix deps): 1.7.14
- Operating system: Linux Ubuntu 22.04 LTS
Actual behavior
Phoenix.Controller.accepts/2 will throw a Phoenix.NotAcceptableError if you add "_format=YOUR_FORMAT" to your URL, where YOUR_FORMAT is not in the list of formats passed to Phoenix.Controller.accepts/2. This is fine during development but during production this will result in a 500 status code to be returned. I tested it on the Phoenix Framework home page as well as another website that I knew was written in Phoenix Framework (https://twomillioncheckboxes.com/)
Expected behaviour
A 406 Not Acceptable status code (https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406) should rather be thrown. Another possible behaviour could be to allow the user to specify a default fallback content type so that at the very least there is still something shown on screen.
Interesting! I have multiple Phoenix apps in production where this works correctly. Do you know how to reproduce this from a new project?
For example:
mix phx.new abcdefg --database sqlite3
cd abcdefg
MIX_ENV=prod mix release
PORT=5001 DATABASE_PATH=./db.sqlite SECRET_KEY_BASE=$(mix phx.gen.secret) PHX_SERVER=true _build/prod/rel/abcdefg/bin/abcdefg start
And visiting http://localhost:5001/?_format=xml correctly renders the Not Acceptable
response.
I tried the method you suggested and that resulted in a project with the proper 406 response.
So then I cloned this project, https://github.com/pjullrich/twomillioncheckboxes (it's one of the projects that I knew was live as well as open source). This time I followed the steps suggested on the Phoenix Framework documentation, https://hexdocs.pm/phoenix/deployment.html:
export SECRET_KEY_BASE=$(mix phx.gen.secret)
export DATABASE_URL=ecto://postgres:postgres@localhost/app_dev
mix deps.get --only prod
MIX_ENV=prod mix compile
MIX_ENV=prod mix assets.deploy
PORT=4001 MIX_ENV=prod mix phx.server
I got the project running properly on localhost with a postgresql database running under docker. When I go to localhost:4001 I get the normal website and then when I go to localhost:4001/?_format=json I get the 500 response along with this error message printed in the console:
18:33:03.508 request_id=F97BEEuU1fzJ8MUAAAAF [error] ** (ArgumentError) no "400" json template defined for AppWeb.ErrorJSON (the module does not exist)
(phoenix_template 1.0.4) lib/phoenix/template.ex:248: Phoenix.Template.render_with_fallback/4
(phoenix_template 1.0.4) lib/phoenix/template.ex:126: Phoenix.Template.render_to_iodata/4
(phoenix 1.7.14) lib/phoenix/controller.ex:1008: anonymous fn/5 in Phoenix.Controller.template_render_to_iodata/4
(telemetry 1.2.1) /home/psionicalch/Development/Elixir/OSS/twomillioncheckboxes/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix 1.7.14) lib/phoenix/controller.ex:974: Phoenix.Controller.render_and_send/4
(phoenix 1.7.14) lib/phoenix/endpoint/render_errors.ex:86: Phoenix.Endpoint.RenderErrors.instrument_render_and_send/5
(phoenix 1.7.14) lib/phoenix/endpoint/render_errors.ex:63: Phoenix.Endpoint.RenderErrors.__catch__/5
(bandit 1.5.5) lib/bandit/pipeline.ex:124: Bandit.Pipeline.call_plug!/2
The project is also running phoenix version 1.7.14.
I think this issue with the project specific code rather than an issue with Phoenix. That's my bad, sorry.