You are here

function restws_page_callback in RESTful Web Services 7.2

Same name and namespace in other branches
  1. 7 restws.module \restws_page_callback()

Menu page callback.

Parameters

string $resource: The name of the resource.

string $page_callback: The page callback to pass through when the request is not handled by this module. If no other pre-existing callback is used, 'drupal_not_found' should be passed explicitly.

mixed $arg1,...: Further arguments that are passed through to the given page callback.

1 string reference to 'restws_page_callback'
restws_menu_alter in ./restws.module
Implements hook_menu_alter().

File

./restws.module, line 335
RESTful web services module.

Code

function restws_page_callback($resource, $page_callback) {

  // Determine the position of the resource and resource id in the path.
  $resource_info = restws_get_resource_info($resource);
  $resource_pos = isset($resource_info['menu_path']) ? count(explode('/', $resource_info['menu_path'])) - 1 : 0;
  $id_arg = arg($resource_pos + 1);
  $resource_arg = arg($resource_pos);
  $format = FALSE;
  $id = NULL;

  // Check for an appended .format string on GET requests only to avoid CSRF
  // attacks on POST requests.
  if ($_SERVER['REQUEST_METHOD'] == 'GET' && ($pos = strrpos($id_arg, '.')) && ($format_name = substr($id_arg, $pos + 1))) {
    $id = substr($id_arg, 0, $pos);
    $format = restws_format($format_name);
  }
  elseif ($_SERVER['REQUEST_METHOD'] == 'GET' && ($pos = strrpos($resource_arg, '.')) && ($format_name = substr($resource_arg, $pos + 1))) {
    $format = restws_format($format_name);
  }
  else {
    $id = $id_arg;
    switch ($_SERVER['REQUEST_METHOD']) {
      case 'POST':
      case 'PUT':

        // Get format MIME type form HTTP Content type header.
        $parts = explode(';', $_SERVER['CONTENT_TYPE'], 2);
        $format = restws_format_mimetype($parts[0]);
        break;
      case 'DELETE':
        if (isset($_SERVER['HTTP_ACCEPT'])) {
          $parts = explode(',', $_SERVER['HTTP_ACCEPT'], 2);
          $format = restws_format_mimetype($parts[0]);
        }
        if (!$format) {

          // We don't care about the format, just pick JSON.
          $format = restws_format('json');
        }
        break;
      default:

        // Get the format MIME type form the HTTP Accept header.
        // Ignore requests from web browsers that accept HTML.
        if (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'html') === FALSE) {

          // Use the first MIME type.
          $parts = explode(',', $_SERVER['HTTP_ACCEPT'], 2);
          $format = restws_format_mimetype($parts[0]);
        }

        // Consumers should not use this URL if page caching is enabled.
        // Drupal's page cache IDs are only determined by URL path, so this
        // could poison the HTML page cache. A browser request to /node/1 could
        // suddenly return JSON if the cache was primed with this RESTWS
        // response.
        if ($format && !isset($_COOKIE[session_name()]) && variable_get('cache')) {

          // Redirect to the URL path containing the format name instead.
          drupal_goto($_GET['q'] . '.' . $format
            ->getName(), array(
            'query' => drupal_get_query_parameters(),
          ), 301);
        }
    }
  }
  if ($format) {
    switch ($_SERVER['REQUEST_METHOD']) {
      case 'POST':
        $op = 'create';
        break;
      case 'PUT':
        $op = 'update';
        break;
      case 'DELETE':
        $op = 'delete';
        break;
      default:
        if (!empty($id)) {
          $op = 'view';
        }
        else {
          $op = 'query';
        }
    }

    // CSRF protection on write operations.
    if (!in_array($_SERVER['REQUEST_METHOD'], array(
      'GET',
      'HEAD',
      'OPTIONS',
      'TRACE',
    )) && !restws_csrf_validation()) {
      restws_terminate_request('403 Forbidden', '403 Access Denied: CSRF validation failed');
    }
    $payload = file_get_contents('php://input');
    if ($file = variable_get('restws_debug_log')) {
      $log = date(DATE_ISO8601) . "\n";
      $log .= 'Resource: ' . $resource . "\n";
      $log .= 'Operation: ' . $op . "\n";
      $log .= 'Format: ' . $format
        ->mimeType() . "\n";
      $log .= 'Id: ' . $id . "\n";
      $log .= 'Payload: ' . $payload . "\n";
      $log .= "----------------------------------------------------------------\n";
      file_put_contents($file, $log, FILE_APPEND);
    }
    restws_handle_request($op, $format, $resource, $id, $payload);
  }

  // @todo: Determine human readable URIs and redirect, if there is no
  // page callback.
  // Fall back to the passed $page_callback and pass through more arguments.
  $args = func_get_args();
  return call_user_func_array($page_callback, array_slice($args, 2));
}