oon arfiandwi
oon arfiandwi

Reputation: 555

How to change Drupal services default response format to JSON?

I'm using Drupal services with REST server to provide API.
Previously I only work with 1 type of response, JSON, so I didn't need extra extension ".json" to the URL.

Now I have to add new formatter, XML.
Then the problem begin, all API without any extension (.json or .xml) will be set default output to XML.

I try to trace this problem, and finally found the related variable is 'rest_server_default_response_format'.
and the related code on services module is getResponseFormatContentTypeNegotiations

So i have $mime_candidates[] value

Array ( [0] => application/xml [1] => text/xml [2] => application/json )

Even the response_format already set as json on line 87, but the mimeparse->best_match() return 'text/xml'.

what the best way to override this?
i don't think edit the getResponseFormatContentTypeNegotiations is the best way.
is there anyway to make the best_match function prefer format JSON than XML?

thank you.

Upvotes: 4

Views: 1755

Answers (3)

Dane Rossenrode
Dane Rossenrode

Reputation: 212

In the latest version of Services, all the action happens in getResponseFormatContentTypeNegotiations() in the services/servers/rest_server/includes/ServicesContentTypeNegotiator.inc file; specifically, this part:

// Get the best matching format, default to json
$response_format = variable_get('rest_server_default_response_format', 'json');
$http_accept = $context->getServerVariable('HTTP_ACCEPT');
if (!empty($http_accept)) {
  $mime = $this->mimeParse();
  $mime_type = $mime->best_match($mime_candidates, $http_accept);
  $response_format = isset($mime_map[$mime_type]) ? $mime_map[$mime_type] : '';
}

What's happening is it's getting a default of formatter of JSON. Then it's looking at your request's accept headers. If your accept headers don't specify a valid MIME type, it's going to use JSON.

It seems all modern browsers have this feature called 'content negotiation', where by default they essentially specify that they accept HTML first, then XML (though this varies by browser).

So considering this, you'd expect that clients would simply need to remove the XML mimetypes from their request header to get JSON. Not so unfortunately.

If the request includes any 'accept' header at all, the code will try to match the header to the list of parsers you've enabled (let's say it's just XML, JSON), and it will either pick one that matches, or the first one. So if you do have an accept header and don't specify a valid MIME type, Services will use the first one you've enabled.

To change the order of those parsers you've enabled, I think you could use one of hooks from services.alter.api.php.

Upvotes: 1

Craig Hawes
Craig Hawes

Reputation: 26

Via the admin UI you can modify configured services to only return certain formats.

Structure> Services

then edit resources > server tab

then you can select response formats and make it exclusively json.

Upvotes: 1

Jean
Jean

Reputation: 11

Best way is to use "Accept" header on your request:

Accept: application/json

If json available it will be used as response instead of xml.

Upvotes: 1

Related Questions