Drupal服务端点返回404:找不到资源检索

时间:2013-12-11 23:20:36

标签: web-services rest drupal drupal-7

我遵循了这个教程: http://pingv.com/blog/an-introduction-drupal-7-restful-services 似乎每个人在评论中都有与我相同的问题。

我使用drupal服务模块进行了休息服务: 服务器= REST path = api / mohtadoon


mohtadoon_api.module文件

<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
  $api = array(
    'mohtadoon' => array(
      'operations' => array(
        'retrieve' => array(
          'help' => 'Retrieves mohtadoon data',
          'callback' => 'mohtadoon_api_stories_retrieve',
          'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
          'access arguments' => array('access content'),
        ),
      ),
    ),
  );
  return $api;
}

资源/ mohtadoon_api路径中的

mohtadoon_api.inc文件

<?php
function mohtadoon_api_stories_retrieve() {
  return mohtadoon_api_find_stories();
}

function mohtadoon_api_find_stories() {
  // Compose query
  $query = db_select('node', 'n');
  $query->join('node_revision', 'v', '(n.nid = v.nid) AND (n.vid = v.vid)');
  $query->join('users', 'u', 'n.uid = u.uid');
  $query->join('field_data_body', 'b', '((b.entity_type = \'node\') AND (b.entity_id = n.nid) AND (b.revision_id = n.vid))');
  $query->fields('v', array('timestamp', 'title'));
  $query->addField('u', 'name', 'author');
  $query->addField('b', 'body_value', 'content');
  $query->condition('n.type', 'stories', '=');
  $items = $query->execute()->fetchAll();
  return $items;
}
?>

当我访问路径时

http://localhost/mohtadoon01/?q=api/mohtadoon/retrieve

其中mohtadoon01是项目路径AND?q =因为

请求结果为404未找到:找不到资源检索。

为什么会发生这种情况&amp;&amp;如何调试这样的东西...我之前没有处理drupal,只想制作一个Web服务。

2 个答案:

答案 0 :(得分:1)

我使用Services 7.x-3.7遇到了完全相同的事情。为了解这个问题,我查看了以下文件:

services/servers/rest_server/includes/RESTServer.inc

根据您的服务定义,GET请求对您的资源执行的代码应为:

protected function resolveController($resource, &$operation) {

  ...

  if (   $request_method == 'GET'
      && $canon_path_count >= 1
      && isset($resource['operations']['retrieve'])
      && $this->checkNumberOfArguments($canon_path_count, $resource['operations']['retrieve'])
      && !empty($canonical_path_array[0])
    ) {
    $operation_type = 'operations';
    $operation = 'retrieve';
  }

  ...

}

如果我们现在看一下$ this-&gt; checkNumberOfArguments()的代码:

// We can see from the snippet above that $args_number = $canon_path_count and hence that
// $args_number is always greater than 0
protected function checkNumberOfArguments($args_number, $resource_operation, $required_args = 0) {
  $not_required_args = 0;

  if (isset($resource_operation['args'])) {
    foreach ($resource_operation['args'] as $argument) {
      if (isset($argument['source']) && is_array($argument['source']) && isset($argument['source']['path'])) {
        if (!empty($argument['optional'])) {
          $not_required_args++;
        }
        else {
          $required_args++;
        }
      }
    }
  }

  // This is where we fall down; Since the service definition does not include any args,
  // both $required_args and $not_required_args will equal zero when we get here. Not a problem
  // for the first condition (1 >= 0), but clearly the second condition (1 <= 0 + 0) will evaluate
  // to false and hence the argument count will not be accepted. As a result, the services module
  // does not accept this controller and reports this as '404 not found'
  return $args_number >= $required_args && $args_number <= $required_args + $not_required_args;
}

尝试在服务定义中添加一个参数,如下所示:

<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
  $api = array(
    'mohtadoon' => array(
      'operations' => array(
        'retrieve' => array(
          'help' => 'Retrieves mohtadoon data',
          'callback' => 'mohtadoon_api_stories_retrieve',
          'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
          'access arguments' => array('access content'),
          'arg' => array(
            array(
              'name' => 'entity',
              'type' => 'string',
              'description' => 'Entity to operate on',
              'source' => array('path' => '0'),
              'optional' => TRUE,
              'default' => '0',
            ),
          ),
        ),
      ),
    ),
  );
  return $api;
}

编辑:

我认为阅读您链接到的博客帖子(我是其中之一!)的令人困惑的是,作为服务的访问者提供的URL包括作为其最终参数的方法的名称打算调用('检索')。您可以用几乎任何东西替换'检索',服务仍然应该响应(例如'/ api / blog / pink-rabbit'或者,在您的情况下,'api / mohtadoon / pink-rabbit')。 Web服务定义本身并不指示可以将哪些参数值传递给端点。重要的是使用HTTP方法访问服务以及将多少参数传递给端点(零个或多个)。某些类型的操作需要至少一定数量的参数(例如,“检索”操作需要至少一个参数来标识您要检索的特定事物。)

答案 1 :(得分:0)

您可能需要对字符串进行网址编码:

http://localhost/mohtadoon01/?q=api%2Fmohtadoon%2Fretrieve

不能保证这会有效,具体取决于你的drupal配置。

根据RFC:http://ietf.org/rfc/rfc3986.txt,查询字符串中允许斜杠,但是开箱即用的许多服务都没有:您可能需要启用AllowEncodedSlashes