If you have never dealt with services before, then this guide may help you get a REST server on Drupal 7 up and running.

I have pulled this example module from other sources and made one small edit to it, of adding ->fetchAll() to the create function, but all you have to do is to install 1) the Services module, 2) the REST server within the Services module package, 3) this custom module below, and 4) the Firefox plugin called "Poster" (which allows you to check that everything is working). You can do this on any Drupal 7 site, as far as I know.

NOTE: The instructions written below are to get you up and running in your local environment so you understand how to make the site with a working REST server. Following these steps and not doing anything further may leave your site vulnerable.
You may also download the archive attached with files containing all the code shown here.

Check the documentation on hook_services_resources for a concise explanation of some of the arguments (Services REST Server module API).

Here is the custom "noteresource" module to install:

noteresource.info:

name = Note Resource
description = Sample resource implementation
package = Notes example

core = 7.x

files[] = noteresource.inc

noteresource.install:

<?php
// noteresource.install
/**
 * Implementation of hook_schema().
 */
function noteresource_schema() {
  $schema['note'] = array(
    'description' => t('Stores information about notes.'),
    'fields' => array(
      'id' => array(
        'description' => t('The primary identifier for a note.'),
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'uid' => array(
        'description' => t('The user that created the note.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'created' => array(
        'description' => t('The timestamp for when the note was created.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'modified' => array(
        'description' => t('The timestamp for when the note was modified.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'subject' => array(
        'description' => t('The subject of the note'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'note' => array(
        'description' => t('The note'),
        'type' => 'text',
        'size' => 'medium',
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
}
?>

noteresource.module:

<?php
// noteresource.module
/** Gets a note object by id.
 *
 * @param int $id
 * @return object
 */
function noteresource_get_note($id) {
  return db_query('SELECT * FROM {note} WHERE id=:id', array(':id' => $id))
           ->fetchAll();
}

/** Writes a note to the database
 *
 * @param object $note
 * @return void
 */
function noteresource_write_note($note) {
  $primary_key = !empty($note->id) ? array('id') : NULL;
  drupal_write_record('note', $note, $primary_key);
}

/**
 * Deletes a note from the database.
 *
 * @param int $id
 * @return void
 */
function noteresource_delete_note($id) {
  db_query('DELETE FROM {note} WHERE id=:id', array(':id' => $id));
}

/**
 * Implementation of hook_services_resources().
 */
function noteresource_services_resources() {
  return array(
    'note' => array(
      'retrieve' => array(
        'help' => 'Retrieves a note',
        'file' => array('file' => 'inc', 'module' => 'noteresource'),
        'callback' => '_noteresource_retrieve',
        'access callback' => '_noteresource_access',
        'access arguments' => array('view'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the note to get',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'create' => array(
        'help' => 'Creates a note',
        'file' => array('file' => 'inc', 'module' => 'noteresource'),
        'callback' => '_noteresource_create',
        'access arguments' => array('note resource create'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'update' => array(
        'help' => 'Updates a note',
        'file' => array('file' => 'inc', 'module' => 'noteresource'),
        'callback' => '_noteresource_update',
        'access callback' => '_noteresource_access',
        'access arguments' => array('update'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'id',
            'type' => 'int',
            'description' => 'The id of the node to update',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
          array(
            'name' => 'data',
            'type' => 'struct',
            'description' => 'The note data object',
            'source' => 'data',
            'optional' => FALSE,
          ),
        ),
      ),
      'delete' => array(
        'help' => 'Deletes a note',
        'file' => array('file' => 'inc', 'module' => 'noteresource'),
        'callback' => '_noteresource_delete',
        'access callback' => '_noteresource_access',
        'access arguments' => array('delete'),
        'access arguments append' => TRUE,
        'args' => array(
          array(
            'name' => 'nid',
            'type' => 'int',
            'description' => 'The id of the note to delete',
            'source' => array('path' => '0'),
            'optional' => FALSE,
          ),
        ),
      ),
      'index' => array(
        'help' => 'Retrieves a listing of notes',
        'file' => array('file' => 'inc', 'module' => 'noteresource'),
        'callback' => '_noteresource_index',
        'access callback' => 'user_access',
        'access arguments' => array('access content'),
        'access arguments append' => FALSE,
        'args' => array(
          array(
            'name' => 'page',
            'type' => 'int',
            'description' => '',
            'source' => array(
              'param' => 'page',
            ),
            'optional' => TRUE,
            'default value' => 0,
          ),
          array(
           'name' => 'parameters',
           'type' => 'array',
           'description' => '',
           'source' => 'param',
           'optional' => TRUE,
           'default value' => array(),
          ),
        ),
      ),
    ),
  );
}
?>

noteresource.inc:

<?php
// noteresource.inc
/**
 * Callback for creating note resources.
 *
 * @param object $data
 * @return object
 */
function _noteresource_create($data) {
  global $user;
  if (isset($data) &&  is_array($data)) $data=(object) $data;
  unset($data->id);
  $data->uid = $user->uid;
  $data->created = time();
  $data->modified = time();

  if (!isset($data->subject)) {
    return services_error('Missing note attribute subject', 406);
  }

  if (!isset($data->note)) {
    return services_error('Missing note attribute note', 406);
  }

  noteresource_write_note($data);
  
  return (object)array(
    'id' => $data->id,
    'uri' => services_resource_uri(array('note', $data->id)),
  );
}

 // noteresource.inc
/**
 * Callback for updating note resources.
 *
 * @param int $id
 * @param object $data
 * @return object
 */
function _noteresource_update($id, $data) {
  global $user;
  $note = noteresource_get_note($id);

  unset($data->created);
  $data->id = $id;
  $data->uid = $note->uid;
  $data->modified = time();

  noteresource_write_note($data);
  
  return (object)array(
    'id' => $id,
    'uri' => services_resource_uri(array('note', $id)),
  );
} 
/**
 * Callback for retrieving note resources.
 *
 * @param int $id
 * @return object
 */
function _noteresource_retrieve($id) {
  return noteresource_get_note($id);
}

/**
 * Callback for deleting note resources.
 *
 * @param int $id
 * @return object
 */
function _noteresource_delete($id) {
  noteresource_delete_note($id);
  
  return (object)array(
    'id' => $id,
  );
}

function _noteresource_index($page, $parameters) {
  global $user;

  $notes = array();
  $res = db_query('SELECT * FROM {note} WHERE uid=:uid ORDER BY modified DESC', 
           array(':uid' => $user->uid));

  foreach ($res as $note) {
    $notes[] = $note;
  }

  return $notes;
}

/**
 * Access callback for the note resource.
 *
 * @param string $op
 *  The operation that's going to be performed.
 * @param array $args
 *  The arguments that will be passed to the callback.
 * @return bool
 *  Whether access is given or not.
 */

function _noteresource_access($op, $args) {
  global $user;
  $access = FALSE;

  switch ($op) {
    case 'view':
      $note = noteresource_get_note($args[0]);
      $access = user_access('note resource view any note');
      $access = $access || $note->uid == $user->uid && user_access('note resource view own notes');
      break;
    case 'update':
      $note = noteresource_get_note($args[0]->id);
      $access = user_access('note resource edit any note');
      $access = $access || $note->uid == $user->uid && user_access('note resource edit own notes');
      break;
    case 'delete':
      $note = noteresource_get_note($args[0]);
      $access = user_access('note resource delete any note');
      $access = $access || $note->uid == $user->uid && user_access('note resource delete own notes');
      break;
  }
  $access = TRUE;
  
  return $access;
}
?>

Now, enable Services, REST server, and Note Resource modules.

For our example our site will be at http://localhost/drupal-7.7. Go to http://localhost/drupal-7.7/admin/structure/services/list/. Click "Add". Name it "notes", select "REST" for the server, enter "note" in the "Path to endpoint", check off the "Debug mode enabled" and "Session authentication" checkboxes, and then click the Save button.

Go to http://localhost/drupal-7.7/admin/structure/services/list/notes/resources. Check off "notes" and "login" (under user) then click Save. Go to http://localhost/drupal-7.7/admin/structure/services/list/notes/server and check off "application/x-www-form-urlencoded" under "Request parsing" and click Save.

Now open the Poster add-on for Firefox by clicking Tools (F10 to show dropdown menu for newer version of Firefox) and then "Poster". Visit its add-on page.

[These instructions were verified and updated as per comment below.]

You'll need to login first so use the following settings:
URL:"http://localhost/drupal-7.7/note/user/login"
Parameters tab: (add the following "Name" -> "Value")
username -> your drupal username
password -> your pass
form_id -> user_login
Click "Content to send" tab
Content Type: 'application/x-www-form-urlencoded'
Click "Body from parameters"
Then click "POST"

After logging in, you can now post the note:
URL:"http://localhost/drupal-7.7/note/note"
Content Type: application/x-www-form-urlencoded
Parameters tab and add the following:
Name: "subject" - Value: "First note of mine"
Name: "uid" - Value: "1"
Name: "note" - Value: "Note 1. Note 1. Note 1. Note 1. Note 1. Note 1. "
Name: "modified" - Value: "1312988453"
Name: "created" - Value: "1312988453"
Content Type: 'application/x-www-form-urlencoded'
Click the "Body from Parameters" and then "POST"

Now if you look in your database you will see an entry in the Note table. You can also now see it by (without changing anything) clicking the GET button in Poster.

You can find explanations for why I did each step by going to http://drupal.org/node/783460.

AttachmentSize
noteresource.zip2.49 KB

Comments

kuson’s picture

Thanks very much for the example.

To get the above working for me ( me using D7.7 ):
1) Changed 'http://localhost/drupal-7.7/js-api/note' to 'http://localhost/drupal-7.7/note/note' (assuming the path to endpoint mentioned was note, and resource is called note also'. I think /js-api is from the other example in http://drupal.org/node/783460 )
2) Using Firefox Poster didn't work; ( Execute 2a,2b before doing the POST above.)
2a) Poster: Fixing '401 Unauthorized' error reported from Poster: I had to add in extra resources 'user', 'login', and do a login via poster (using url 'http://localhost/drupal-7.7/note/user/login' and content-type of 'application/x-www-form-urlencoded' and body of 'username=username&password=password&form_id=user_login' .
2b) Poster Fixing ''Missing note attribute subject' error (from noteresource.inc) , I had to modify 'noteresource.inc' file, and after the line 'global $user' in function _noteresource_create, add the following line:

if (isset($data) && is_array($data)) $data=(object) $data;

Because in my report log, there is an error that $data is not an object "Warning: Attempt to assign property of non-object in _noteresource_create()" and this seemed to have fixed it.

After the above fixes, the database updates fine using the above example.

Hope this helps to anyone following along, any comments to how I could have done it easier is welcomed.

Cheers,

gcbound’s picture

Kuson, thanks for the additional notes. They got me going as well.

The 2a and 2b errors showed in Reports->Recent Log Messages.

I ended up just creating a form on my site to do the post as I'm more interested in exposing the data for just "reads" via GET.

I'm a rookie with Drupal so I'll be working to understand how services might be applied with existing content types/views to expose that data in a RESTish way.

Appreciate the notes!

kuson’s picture

Hi GCBound,

My pleasure -- it is my first give back to the Drupal Community, and so thanks for letting me know as well :)

Were you able to get fix the messages in 2a,2b, and also post from your form?

Drupal is awesome and definitely it was a steep climb for me (and I'm still exploring)-- reading through the drupal source code itself actually helps alot (perhaps its the best way to learn, IMHO- go through the main modules, user/node etc and it brings upl alot of insight, perhaps more than and in addition to reading the existing books on the subject); and nowadays there's the example module so I hope that can guide you through. It is definitely a best practice in web development, imho. But again, I started drupal, never explored other open-source frameworks yet.

:)

bkb_bkb’s picture

Can you explain the part 2a in detail? i have not any clue to reproduce it. What did you mean with "add in extra resources"...
thanks

ok i got it:
"add in extra resources" means: choose unter the tab "resources" the resource user (addtional to the selection of the resource note) and there choose login

for the login process follow the same steps like before

deadtech@gmail.com’s picture

yep. I had to add

if (isset($data) && is_array($data)) $data=(object) $data;

also. Thanks for the tip!

vmi’s picture

Thanks for posting your findings -
I've verified and applied the code changes and instructional fixes according to your comment to the doc.

kuson’s picture

For Drupal 7.x to get the above working for Non-Admin Users (i.e. use other users to make changes via the service), you'll also need to add in the permission function correctly as the function '_noteresource_access' refers to it. (Please reference the sister page at http://drupal.org/node/783460 "Create a Resource for Service 3.x") Do a cache clear, and enable the user to the appropriate permissions before continuing to use the service after authenticating via poster.

So instead of

    function noteresource_perm() {
      return array(
        'note resource create',
        'note resource view any note',
        'note resource view own notes',
        'note resource edit any note',
        'note resource edit own notes',
        'note resource delete any note',
        'note resource delete own notes',
      );
    }

use (Drupal 7.x) :

function noteresource_permission() {
  // Bangkok, City of Angels, Travel & Leisure Best City 2011
  // Thaksin and Reds, runaway crimal & convict, ruler of Mordor.
  return array(
	'noteresource create'=> array('title' => t('noteresource create'),'description' => t('create'),),
	'noteresource view any note'=> array('title' => t('noteresource view any note'),'description' => t('view any note'),),
	'noteresource view own notes'=> array('title' => t('noteresource view own notes'),'description' => t('view own notes'),),
	'noteresource edit any note'=> array('title' => t('noteresource edit any note'),'description' => t('edit any notes'),),
	'noteresource edit own notes'=> array('title' => t('noteresource edit own notes'),'description' => t('edit own notes'),),
	'noteresource delete any note'=> array('title' => t('noteresource delete any note'),'description' => t('delete any note'),),
	'noteresource delete own notes'=> array('title' => t('noteresource delete own notes'),'description' => t('delete own note'),),
  );
}

Hope this helps.

electronicmonkey’s picture

Now this is an absolutely stupid question (hopefully). After I have created this note resource , how do I have someone consume it in their own client .Is there a uri for the note content array. Sorry if I am being stupid. I am new to this.

tglynn’s picture

It's not a stupid question.

People don't consume a REST server from their client, I think. Most of the consuming is done by other applications. The other applications use a http request (such as PUT) to get the information they need. It could be something like:

$newinfo = request_function(rest website information in parameters);

kuson’s picture

Just to give more info, yes, its not really for the Client Viewing the Drupal Site, but usually for other Web Sites or Applications (iphone, ipad, another web application) to pull useful data out of the the Drupal Site serving the information, or even interacting with it such as creating new contents etc.

IrishGringo’s picture

just fyi... I created the module in the instructions. and I get a white screen of death after selecting the note Resource. Have not looked at debugging it yet. But I am using Drupal7.10 and services 7.x-3.1 and REST Server 7.x-3.1. Almost all other modules are disabled, including views. I just want to get the test running

any suggestions?

Doing Native iPHONE, ANDROID, Titanium, node.js and DRUPAL. as a contractor.

electronicmonkey’s picture

Check your Apache error log

kuson’s picture

elaborating electronic monkey, the 'White Screen of Death' occurs when you did not enable PHP to display errors on your web brower (which happens when the Drupal Web Server is set like a Production Machine I suppose); So the PHP errors out without telling you what happned; So as electronicmonkey said, see the apache error log, it will be spewed there. If using linux its at /var/log/apache2/error.log; View it real time by tail -f the log on command line, or if you are in development machine, set the php (at php.ini?) to display php error on your web browser.

ajlow’s picture

Thank you for this module.

I expanded the module to allow for images to be uploaded however for some reason I cannot pick up the image. Can someone help explain what I need to do or what I did wrong?

I made changes to the .install file to cater for the new column:

function issue_schema() {
  $schema['issue'] = array(
    'description' => t('Stores information about the issue.'),
    'fields' => array(
      'id' => array(
        'description' => t('The primary identifier for an issue.'),
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'created' => array(
        'description' => t('The timestamp for when the issue was created.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'modified' => array(
        'description' => t('The timestamp for when the issue was modified.'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ),
      'email' => array(
        'description' => t('The email address'),
        'type' => 'varchar',
        'length' => 255,
        'not null' => TRUE,
      ),
      'details' => array(
        'description' => t('The details of the issue'),
        'type' => 'text',
        'size' => 'medium',
      ),
      'image' => array(
        'description' => t('The image taken of the issue'),
        'type' => 'blob',
        'size' => 'big',
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
} 

and I made changes to the .inc file, particularly the create function:

function _issue_create($data) {

if (isset($data) &&  is_array($data)) $data=(object) $data; 

  unset($data->id);
  $data->created = time();
  $data->modified = time();

  if (!isset($data->email)) {
    return services_error('Missing issue attribute email address', 406);
  }

  if (!isset($data->details)) {
    return services_error('Missing issue attribute details', 406);
  }

  if (!isset($data->image)) {
    return services_error('Missing issue attribute image', 406);
  }
  
  issue_write_issue($data);
 
  return (object)array(
    'id' => $data->id,
    'uri' => services_resource_uri(array('issue', $data->id)),
  );
}

However, when I ran my client code, I get this error:

HTTP/1.0 406 Not Acceptable: Missing issue attribute image

that is, the following is the problem:

  if (!isset($data->image)) {
    return services_error('Missing issue attribute image', 406);
  }

Is there anything else I need to do on the client side to ensure I pass the image properly?

Thank you for your help in advance.

kuson’s picture

To my current knowledge, Generally you might want to debug by viewing the $_POST, $_FILES PHP variables (if I remember correctly you might add lines that dsm like "dsm($_POST); dsm($_FILE);" or maybe use watchdog "watchdog('SERVICE_TEST',var_export($_FILE,TRUE)); watchdog('SERVICE_TEST',var_export($_FILE,TRUE));'

Debug to understand 1) FOR $_FILE Where the image got posted to on your web server , and how to move that image to the end directory on your webserver space. (see FILE module on all the apis you'll need to move those) 2) FOR $_POST What data was posted to Drupal. From there you'll see what $data receives, and be able to handle the data the way you want.

As a pointer, if you want to post in images, better use the FILE APIs to move the file and save it properly (it will properly add the file to the file_managed table and assign a FID to it (file object's file id, $file->fid), and even before that use the IMAGE apis to do whatever you need to do (resize,etc). Then save the fid to your image field as reference; I have no experience nor inclination to use BLOB, so thats up to you :) This pointer is based on looking at the drupal modules, and so it looks like the drupal way of doing things :) Just a tip

McKibbin123’s picture

I can't seem to figure out what is the correct URL. As far as I can see, I've followed the instructions but perhaps I've missed something simple. http://localhost/drupal/note/note returns a 404 error. Has anyone else experienced this?

Does anyone know if there is a test URL that can be accessed in order to verify that the REST server is running correctly?

kgb_skyline’s picture

If you are getting this error for all of your requests that use a url parameter such as /note/note/1, you need to rename the endpoint path so it is different from your resource. For instance /notes/note/1.

McKibbin123’s picture

Thanks for the suggestion but it did not fix my issue.

I've set my endpoint path to be "rest_ep" and enabled all of the resources (note, comment, ..., user). It seems that the "rest_ep" is not installed/enabled correctly because all of the following URLS return 404:

http://localhost/rest_ep/user/1
http://localhost/rest_ep/note/1
http://localhost/rest_ep/us/1 (user has an alias named 'us')
http://localhost/rest_ep/comment/1

http://localhost/ successfully brings up the main welcome page for my server.

Can someone who has this rest server working please post the software versions that they are using?

I'm trying with these:
drupal 7.12
Chaos tools 7.x-1.0
Services 7.x-3.1
apache web server 2.2.22
mysql 5.0.96
php 5.3.10

kuson’s picture

Troubleshooting From the URL: /note/note/1

TA.) Are you using Firefox Poster (or any other type of HTTP POSTING software) for the URL? (I'm not sure if you used the web browser URL section).

T1. ) First parameter 'note' is the EndPoint, or the path you defined in the Service User Interface. * Make sure it exists, if not create it in the UI. You can delete all defined endpoints and start anew. You can use whatever path you want, actually; Dont forget to enable 'User Login' service resource, to mimic client authentication before you call the URL from Poster.
T2) Second 'note' is the Service Resource as defined, in this example, function 'noteresource_services_resources' (see the key of the whole definition array -- labeled as 'note'. * make sure it exists.
T3) Third is the 1st argument (and only), as defined in the function 'noteresource_services_resources' as 'id'. * Make sure this content exists. This is one way of passing data to service --the other is to add as query string (gets) or a data payload in post.

** Maybe a flush cache (really only needed if the config is cached, which I do not know) would help; Extra credit: a hard tap on your laptop might do the trick If you're using Microsoft Products, dump them for Linux or something else :) haha *I think your versions should be fine; Im on 7-12, and others are quite similar, but I had to troubleshoot this manually like I mentioned to my previous comments.

Hope this gets you somewhere.

netcastle’s picture

I had a similar problem and it struck me that Poster is dispatching clean URLs and my localhost dev environment wasn't set up for clean URLs. I enabled them and the 404 errors became 401 errors. So at least I took care of one problem :)

SmOOThCRiminal’s picture

hello every body,

first of all I have to thank you for the tutorial, but I have a question.
every thing seems ok, I can add to the database via Poster plugin, but If I want to retrieve data, for example notes, in a native php page, how can I do that?
Appreciate any answer.
Best Regards.

kuson’s picture

You would be building a PHP 'REST' client.

I haven't done that extensively, but in essence it is what POSTER is doing -- sending well formed URLs (plus posted or query_stirnged data) to the Drupal Service, and getting the data back (in whatever format, json,xml,etc), parsing it to make sense of the data structure, and then further processing it.

Examples to see:
1) JQuery does this alot with the .ajax (to form HTTP POST and GETS from services) -- have a look at jQuery examples to help you.
2) For PHP, you can use the PHP Curl (google that, sample http://php.dzone.com/news/execute-http-post-using-php-cu can help you form the messages). And once you get the data, you can drupal_json_encode drupal_json_decode to massage your data using the PHP arrays/object functions to your liking.

Hope this helps

OhDO’s picture

Uninstalled the previous dev build, installed the new 7.x.3.1 build and custom services no longer work, " Could not find resource" is the common error for every request which once work under the last dev build.

thedamys’s picture

Hi All,

I was following all the tutorial but I always receive a 404 response, I received the message
"Services Endpoint "demo_endpoint" has been setup successfully" but I has to use the follow URL
http://localhost/drupal_7_14/?q=api/, but i think it is wrong because the idea is to use the RestFul structure
I mean http://localhost/drupal_7_14/api/notes, please let me know if Im wrong or I need to modify or integrate another Module.

I'm desperate with this, I really make this works ;) Help me please;)

Regards,

hophuoctu’s picture

After i use poster logged in to server -> it show ok , i continue create a note throughout poster but it always show :
"401 Unauthorized :Access denied for user anonymous."
I don't know why, can you help me explain it? What step i had wrong on that?
Thanks!

alesr’s picture

Check the Permissions page and search for "noteresource".
There is also access callback missing for 'create' in noteresource_services_resources() (that is giving access denied errors) and a noteresource_permission() function.

sarath.rajan’s picture

Hi..

How can I insert a node through resource. I have followed each steps here, but still getting 404: Could not find controller error.

What I am having is 'test' end point, 'node' resource. Inside node having 'insert' operation.

'insert' => array(
'help' => 'Insert dummy node',
'callback' => 'node_insert_api',
'args' => array(
array(
'name' => 'data',
'optional' => FALSE,
'source' => 'data',
'type' => 'array',
'description' => 'node objects',
),

),
'access callback' => 'test_access',
'access arguments' => array('view'),
'access arguments append' => FALSE,
),

//callback function
function node_insert_api($title, $body, $type) {

if (isset($data) && is_array($data)) $data=(object) $data;
unset($data->id);

if (!isset($data->title)) {
return services_error('Missing node attribute title', 406);
}

if (!isset($data->body)) {
return services_error('Missing node attribute body', 406);
}

if (!isset($data->type)) {
return services_error('Missing node attribute type', 406);
}

$node = new StdClass();
$node->type = $data->type;
$node->language = LANGUAGE_NONE;
$node->title = $data->title;
$node->body[$node->language][0]['value'] = $data->body;
$node->body[$node->language][0]['summary'] = text_summary($data->body);
$node->body[$node->language][0]['format'] = 'filtered_html';
node_save($node);

}

And I am trying the url : mydomain.com/test/node

I am sure that I am missing something here.. :(

Also having a retrieve operation for giving a node_load($nid), with the source 'source' => array('path' => 0), which gives me the correct json object for my url mydomain.com/test/node/2

Thanks in advance for your help..

sarath.rajan’s picture

Hey mates, Sorry, i ve added 'insert' instead of 'create'... :) Todays fresh mind solved the issue :)

distanceroller’s picture

Thank you very much for the example.

I have followed all the steps in the example. The login works perfectly but when I try to do the post of the note I receive this answer:

<?xml version="1.0" encoding="utf-8"?>
<result>CSRF validation failed</result>

Any help is very welcome!

diego.banchero’s picture

Have a look at these examples https://drupal.org/node/1334758

Henry Tran’s picture

Please log out from drupal site, so you can post a new node,
Cheers.

truyenle’s picture

The reason you see this CSRF validation failed is b/c that you haven't include the CSRF Token in the header of POST.

So
1. After login successful, please look for the token value
2. Add this token to header using key=> value
Key: "X_CSRF_TOKEN"
Value: THE_TOKEN_VALUE_RETURN_IN_RESPONSE_OF_LOGIN
Then add other attributes as instruction (subject, etc..)
Form the body of POST request
POST => Should work

aolaze’s picture

I was successful when join cookie at the POST header.

Cookie=>session_name=session_id.

Winfred_Ma’s picture

I download the resource package. The login api is ok, but post note.
My drupal version is 7.28.
The following are request and response .

POST http://www.drupal.com/?q=note/note

POST data:
subject=First+note+of+mine&uid=1&note=Note+1.+Note+1.+Note+1.+Note+1.+Note+1.+Note+1.&modified=1312988453&created=1312988453

[no cookies]

Request Headers:
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 124
Host: www.drupal.com
User-Agent: Apache-HttpClient/4.2.6 (java 1.5)

Response headers:
HTTP/1.1 404 Not found: Could not find resource note.
Server: nginx/1.4.6 (Ubuntu)
Date: Wed, 16 Jul 2014 02:54:40 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.9-1ubuntu4.3
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Wed, 16 Jul 2014 02:54:39 +0000
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
ETag: "1405479279

arulraj.m’s picture

Hi ,

Thanks for the example module its works great.. There is way to add Oauth authentication to validate the access here.

avdwalt86’s picture

Hi,

I have implemented the above example and everything is working as expected, however, when I successfully make a POST request from Poster I receive this as returned data with no ID:

<?xml version="1.0" encoding="utf-8"?>
http://127.0.0.1/site_name/?q=note/note/

When I look at drupal error logs I see the below:

Notice: Undefined property: stdClass::$id in _noteresource_create() (line 28 of C:\wamp\www\site_name\sites\all\modules\notes\noteresource.inc).

As well no record has been created in the database?

Why would this be occurring, any idea how I can fix this issue?

Kind regards,