我使用带有REST服务器的Drupal服务来提供API
以前我只处理一种类型的响应,JSON,所以我不需要对URL进行额外的扩展".JSON"。
现在我必须添加新的格式化程序XML
然后问题开始了,所有没有任何扩展(.json或.xml)的API都将被设置为默认输出xml。
我试图跟踪这个问题,最终发现相关变量是"restrongerver_default_response_format"
服务模块上的相关代码为getResponseFormatContentTypeNegotiations
所以我有$mime_candidates[]值
Array ( [0] => application/xml [1] => text/xml [2] => application/json )
即使response_ formatt已经在第87行设置为json,但是mimeparse->best_match()返回"text/xml"。
最好的方法是什么
我不认为编辑getResponseFormatContentTypeNegotiations是最好的方法
有没有办法让best_match函数更喜欢JSON格式而不是XML格式
谢谢。
最好的方法是在您的请求中使用"Accept"标头:
Accept: application/json
如果json可用,它将被用作响应,而不是xml。
通过管理UI,您可以修改配置的服务,使其仅返回某些格式。
结构>服务
然后编辑资源>服务器选项卡
然后,您可以选择响应格式并将其设为json格式。
在最新版本的Services中,所有操作都发生在services/servers/rest_server/includes/ServicesContentTypeNegotiator.inc
文件中的getResponseFormatContentTypeNegotiations()
中;具体来说,这部分:
// 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] : '';
}
现在的情况是,它得到了JSON的默认格式化程序。然后它会查看您请求的接受标头。如果接受标头没有指定有效的MIME类型,那么它将使用JSON。
似乎所有现代浏览器都有一个称为"内容协商"的功能,默认情况下,它们基本上指定先接受HTML,然后接受XML(尽管这因浏览器而异)。
因此,考虑到这一点,您会期望客户端只需从其请求标头中删除XML mimetype即可获得JSON。并非如此不幸。
如果请求包含任何"accept"标头,代码将尝试将标头与您启用的解析器列表相匹配(假设它只是XML、JSON),然后选择匹配的标头或第一个。因此,如果您有一个accept标头,并且没有指定有效的MIME类型,服务将使用您启用的第一个。
要更改已启用的解析器的顺序,我认为可以使用services.alter.api.php
中的一个钩子。