Community Documentation

Example REST server for node.create with session authentification (JSON & PHP cURL)

Last updated September 26, 2012. Created by Raphael Apard on November 7, 2011.
Edited by jackbravo, rachit_gupta, kylebrowning. Log in to edit this page.

Endpoint requirements :

  • Set "Authentification" as "Session authentication"
  • Set "Response formatters" as "json"
  • Check resources "User > Login" and "Node > Create"

User requirements :

  • Add permission to create content type "page" for user role

<?php
/*
* Server REST - user.login
*/

// REST Server URL
$request_url = 'http://your-drupal/rest_server_endpoint/user/login';

// User data
$user_data = array(
 
'username' => 'user_name',
 
'password' => 'user_password',
);
$user_data = http_build_query($user_data);

// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

// Check if login was successful
if ($http_code == 200) {
 
// Convert json response as array
 
$logged_user = json_decode($response);
}
else {
 
// Get error msg
 
$http_message = curl_error($curl);
  die(
$http_message);
}


/*
* Server REST - node.create
*/

// REST Server URL
$request_url = 'http://your-drupal/rest_server_endpoint/node';

// Node data
$node_data = array(
 
'title' => 'A node created with services 3.x and REST server',
 
'type' => 'page',
 
'body[und][0][value]' => '<p>Body</p>',
);
$node_data = http_build_query($node_data);

// Define cookie session
$cookie_session = $logged_user->session_name . '=' . $logged_user->sessid;

// cURL
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json')); // Accept JSON response
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_POSTFIELDS, $node_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

// Check if login was successful
if ($http_code == 200) {
 
// Convert json response as array
 
$node = json_decode($response);
}
else {
 
// Get error msg
 
$http_message = curl_error($curl);
  die(
$http_message);
}

print_r($node);
?>

If Successful

Response code: 200 OK
return node nid and node uri as json

If Unsuccessful

Response codes

401 Unauthorized: Wrong username or password, or user doesn't have right permission.
406 Title field required / type field is required

Comments

Small bug

I think the first instance of

curl_setopt($curl, CURLOPT_POSTFIELDS, $node_data); // Set POST data

should in fact be:

curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data

You right ;). Fixed. Thanks

You right ;). Fixed. Thanks

Raphael

Thanks, good example; But to

Thanks, good example;

But to return Json object after successful login You have to send httpheaders too,

Ad this code to first part of script (User login);

<?php
curl_setopt
($curl, CURLOPT_HTTPHEADER, array('Accept: application/json'));
?>

I added this for the second

I added this for the second part too (also get a json response).

Raphael

To get this to work in

To get this to work in Services 3.x in D6, I had to enable: application/x-www-form-urlencoded in server->request parsing. Otherwise I would get:
The requested URL returned error: 406

Simplistech Solutions - Simplifying technology for small businesses and entrepreneurs.

406 errors

In fact, I use the last services version on drupal 7, and I have got 406 errors too.
When I enable "jsonp" and "application/x-www-form-urlencoded", the first 406 error disappear (during the authentication), but it still appears during the node.create request!

Any idea?

Same 406 error here when I

Same 406 error here when I specify the node author. Anyone have a fix?
'uid' => 10,
'name' => 'myusername',

Thanks.

rest_server_endpoint?

I am not clear on how the request url is constructed in the example:

<?php
$request_url
= 'http://your-drupal/rest_server_endpoint/user/login';
?>

Is rest_server_endpoint a canonical name or a placeholder? In the first case, can someone point met to the documentation, in the second case. how and where is set?

Re: rest_server_endpoint?

rest_server_endpoint is a placeholder. You define endpoints in the services configuration (admin/build/services/add)

image filed

if i have a image filed how i can create node content with image?

drupal_http_request vs cURL?

There are drupal_http_request function , why do you use cURL?

Yes, we can use

Yes, we can use drupal_http_request, but for my example, i call webservice from another device, not from a other drupal.

Raphael

wow.. very nice post. Thanks.

wow.. very nice post.
Thanks.

Trying to get this sample,

Trying to get this sample, the script is returning a 302 error in $http_code var and I don't know what's the problem.
Anybody got the same problem or knows how to resolve it?
Thanks.
Regards

302 isn't an error

302 is the http code for a redirect, it's not an "error" as such.

Finally I could solve this

Finally I could solve this removing a redirect URL Rule that I had activated in Rules Module. Then I got 200 http response. Thanks

I found something really strange.

I have some term references in my custom node so, when I build my node_data I use for instance
$node_data['field_something[und]'] = array(array("tid"=>294));
where field_something is a custom term reference.
I can create a node with term references, using curl. It is working well.

Except for the well known "field_tags", when the default widget for autocomplete is activated.

If I use Autocomplete Deluxe widget for field_tags, the service with curl is working !

I am really surprised of this behavior, should I post it in issues ? and where ? (service ? core ?)

Yann

Revised Code

I could not get the above code to work, so I went through and made some revisions based on other Documentation snippets and got this to work:

<?php
/*
* Server REST - user.login
*/

// REST Server URL
$request_url = 'http://your-drupal/rest_server_endpoint/user/login.json';

// User data
$user_data = array(
 
'username' => 'testuser',
 
'password' => '1password',
);

// cURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $request_url);
curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($user_data)); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, FALSE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);

$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

// Check if login was successful
if ($http_code == 200) {
 
// Convert json response as array
 
$logged_user = json_decode($response);
}
else {
 
// Get error msg
 
$http_message = curl_error($curl);
  die(
$http_message);
}

/*
* Server REST - node.create
*/

// REST Server URL
$request_url = 'http://your-drupal/rest_server_endpoint/node';

// Node data
$node = (object) NULL;
$node->title = 'A node created with services 3.x and REST server';
$node->type = 'page';
$node->body['und'][0]['value'] = '<p>Body</p>';
$node->path = '';
$node_data = (array) $node;

$node_data = json_encode($node_data);

// Define cookie session
$cookie_session = $logged_user->session_name . '=' . $logged_user->sessid;

// cURL
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $request_url);
curl_setopt($curl, CURLOPT_POST, TRUE); // Do a regular HTTP POST
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json')); // Accept
curl_setopt($curl, CURLOPT_POSTFIELDS, $node_data); // Set POST data
curl_setopt($curl, CURLOPT_HEADER, TRUE);  // Ask to not return Header
curl_setopt($curl, CURLOPT_COOKIE, $cookie_session); // use the previously saved session
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, FALSE); //True in prod, false for debugging

$response = curl_exec($curl);

$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

// Check if login was successful
if ($http_code == 200) {
 
// Convert json response as array
 
$node = json_decode($response);
}
else {
 
// Get error msg
 
$http_message = curl_error($curl);
  die(
$http_message);
}

print_r($node);
?>

It's definitely worth

It's definitely worth var_dump-ing the $http_code and $response after they've been defined to find out exactly where things have gone wrong. Particularly with regards to a 406 error (for instance the default D7 node type is basic_page which is easy to miss).

For some reason, I keep

For some reason, I keep getting error 401 although I'm really sure I got the $cookie_session set.

Edit: The solution was to enable "Session authentication" in the edit settings for the services.

I am also getting the 401

I am also getting the 401 error and do not understand it.

I tried the first code sample and only changed the endpoint url to match my site. When i ran this I got a 406 error in the node create section.

I changed to the second code sample and this time I am getting the 401 error suggesting an authorisation failure.

I have checked and I have "Session authentication" set in the edit settings for the service I have created in services.

I am using Drupal 7.14 and Services 3

I would appreciate any idea where to look for this authentication issue.

same here, but I'm using D6

same here, but I'm using D6 instead!!

Try the first code sample and

Try the first code sample and enable "application/x-www-form-urlencoded" in server tab, that's how I fix this problem.

That one works

I only had "application/json" and it was complaining that the title was missing. Then I enabled "application/x-www-form-urlencoded" and it works fine. Thanks.

how to post tags and categories with this script

Nice script, however I want to post tags and category along with node data how can I send it? what parameter should I add in node data array?

$node_data = array(
  'title' => 'A node created with services 3.x and REST server',
  'type' => 'page',
  'body[und][0][value]' => '<p>Body</p>',
);

Page status

Needs updating

Log in to edit this page

About this page

Drupal version
Drupal 6.x, Drupal 7.x
Level
Beginner
Audience
Contributors
Keywords
documentation

Develop for Drupal

Drupal’s online documentation is © 2000-2013 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License. Comments on documentation pages are used to improve content and then deleted.
nobody click here