playframework / playframework/play1

Wrong HTTP status (500) when content negotiation fails

Open
#1,364 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
1.6k
Forks
671
Avg merge
12d 15h
Merged PRs (30d)
1

Description

Play1 has some content negotiation built in. For incoming requests it will try to establish the required return content type based on request header (Accept) and possibly also the extension of the last path segment.

In order to render the content in the requested content type, Play1 will look for a template with a certain extension. If it cannot find that template, it generates a 500 response and puts the following in the logs:

play.mvc.Controller.renderTemplate(Controller.java:813)
play.mvc.Controller.renderTemplate(Controller.java:782)
play.mvc.Controller.render(Controller.java:843)
controllers.SomeController.show(SomeController.java:42)
@7l7kg8b6p Internal Server Error (500) for request GET /some_controller/1234
  Template not found (In {unknown source file.  appclass=controllers.SomeController (compiled:true)} around line 42)
  The template SomeController/show.txt does not exist.

The client will see this:

curl -H "Accept: text/plain" https://example.com/some_controller/1234
Template not found 
The template SomeController/show.txt does not exist.

This behavior from Play1 makes my app very 500 happy. And I want 500s to be reserved for situation where either (a) we made a mistake programming the application, or (b) a service our app depends on is not available.

I'd argue that these 500s should be reclassified as (this is what I expect as behavior):

  • 404 Not Found: in line with the Template not found error (I'd generalize this to resource or object not found).
  • 400 Bad Request: my preference as the application cannot deal with this type of request, it is defacto a request that does not fit with the API specs and hence is a mistake of the client.

500s in this case are a bit too heavy handed.

Maybe there is a way to mitigate this that I'm not aware of. As it looks I'd need to put guards in many of my controllers to prevent these "bad requests" to become 500s. Which leads me to the conclusion that 500s are the wrong default in this case.

I'd gladly submit a PR fixing this, but I'd like to know first if that'd be something the core contributors are interested in. And on top of that we need to figure out what the new status will be (400, 404, or something else) and if this then still requires any logging.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the failure through play.mvc.Controller.renderTemplate and Controller.render, using the example controllers.SomeController.show call and missing SomeController/show.txt template as the scenario. First determine whether content-negotiation failures should return 400 or 404 and how they should be logged; done means the chosen behavior is defined and implemented consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend-api-design
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.