mesosphere / marathon

Deploy and manage containers (including Docker) on top of Apache Mesos at scale.
https://mesosphere.github.io/marathon/
Apache License 2.0
4.07k stars 845 forks source link

Keep the rest-api return format consistent when request headers without "Accept: application/json" #1647

Closed BrickXu closed 9 years ago

BrickXu commented 9 years ago

Hi all,

I found that v2/tasks must set the request header with Accept: application/json to get the json format response, or the marathon will return plain text.

curl -X GET -H "Content-type: application/json" http://localhost:8080/v2/tasks
docker_registry 10004   XXXXXX
logs_statsd 10000   XXXXXX

curl -X GET -H "Content-type: application/json" -H "Accept: application/json" http://localhost:8080/v2/tasks
{"tasks":[{"appId":"/ldocker_registry","id":"docker_registry.e0125d32-0f78-11e5-aa0e-fa163ee98acb","host":"logstash8.ops.com","ports":[9027],"startedAt":"2015-06-10T13:59:13.814Z","stagedAt":"2015-06-10T13:59:13.447Z","version":"2015-06-10T13:59:08.979Z","servicePorts":[10002]},...

But for the v2/apps, it always return json format response without Accept: application/json. I think the APIs must keep the same behavior when the request with or without Accept: application/json

ENV:

pierluigi commented 9 years ago

Actually this is still happening on v0.10.0-RC3:

$ curl 'http://localhost:8080/v2/apps/sleeper/tasks/'
sleeper     172.18.6.104 172.18.6.104

$ curl 'http://localhost:8080/v2/apps/sleeper/tasks/' -H "Accept: application/json"
{"tasks":[{"appId":"/sleeper","id":"sleeper.1c5789ef-3128-11e5-8f1f-ac87a33a1422","host":"172.18.6.104","ports":[],"startedAt":"2015-07-23T10:46:44.924Z","stagedAt":"2015-07-23T10:46:44.862Z","version":"2015-07-23T10:42:14.631Z"},{"appId":"/sleeper","id":"sleeper.1f542820-3128-11e5-8f1f-ac87a33a1422","host":"172.18.6.104","ports":[],"startedAt":"2015-07-23T10:46:49.936Z","stagedAt":"2015-07-23T10:46:49.873Z","version":"2015-07-23T10:42:14.631Z"}]}%
kolloch commented 9 years ago

If you use curl, it always sets the Accept header. If you do not specify anything explicitly, it will use Accept: */*.

The SetRequestDefaultsFilter will only set the Accept header if it was not set before. In the case of Accept: */* it will leave in untouched.

Our routing logic then seems to determine the preference between the different implementation which only differ in their values of the @Produces logic on startup. Thus, if you just restart Marathon often enough, you will get to the state which consistently uses text/plain to answer the above request.

It sucks that this seems to be determined at random on startup.