Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Endpoint requirements :
- Set "Authentication" 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
/**
* Create a token for non-safe REST calls.
**/
function mymodule_get_csrf_header() {
$curl_get = curl_init();
curl_setopt_array($curl_get, array(
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => 'http://your-drupal/services/session/token',
));
$csrf_token = curl_exec($curl_get);
curl_close($curl_get);
return 'X-CSRF-Token: ' . $csrf_token;
}
/*
* 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', mymodule_get_csrf_header())); // 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', mymodule_get_csrf_header())); // 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
NOTE: Many get the 401 error, but this example seems to work for many: https://www.drupal.org/node/1334758#comment-8656123
Comments
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
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:
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
Communication to the service depends on ... the widget !
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 ?)
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:
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?
I believe this sample is
I believe this sample is flawed as there is no need to get csrf token two times. One time is enough after user login. Also, csrf token needs to be obtained in the same curl session as login, as Drupal Services returns empty otherwise...
PS: I also fixed the DrupalREST class here https://github.com/RandallKent/DrupalREST.PHP/issues/2
My Drupal sites:
then response for token is in
then response for token is in json format. to get the token string, try using the following instead.
Thank you.
This one worked for me. I was getting nervous I was no where near grokking this. Thank you.
token from login
I'm using Services 3.7 which gave me the token using this after the login:
$csrf_token = $logged_user->token;
So I didn't need all this from the above example:
it gives 401 access denied error
i am using same code only the url and rest api url is changed, but it gives 401 anauthorized aceess error::
it print csrf-token fine and also login into the remote site fine, but when i want to create a node throught curl then it gives 401...
can anyone give me any idea why this gives 401 error,,
when i try in poster it works fine,
It's working for me
Follow below steps,
Write this simple code in php file
Worked perfectly for me
Worked perfectly for me
-- Pratip Ghosh
doesnt work for me!
rest_connect() keeps returning hash string like below
0kRJ0zv7QVui6i8A4S0E9Z7YBFNW5cc5JeOfpkdVitY
RdqbZg65MS0iQSxp9yGhTMmBShd5ceRR9dbDk_cawqY
etc
$http_code returns 200 correctly
stuck with rest_connect itself.
On Service settings:
Server: Rest
Authentication: Session authentication is selected
Debug mode enabled : Yes
On Server tab:
All options are selected for Response formatters and Request parsing
On Resource tab:
Use.Login and User.Token is selected with Services Resource API Version 1.1 and Crud operation for Create
Cheers
Dinesh Waghmare (LAMP)
UK, Surrey | India, Mumbai
Web Development | Digital Media Marketing | Strategic Consulting
--
m: +91 9867888266
(Drupal / Wordpress / SugarCRM )
This code works for me. I
This code works for me. I finally got rid of 401 errors.
Drupal 7.37
Services 7.x-3.12
Perfect example code
Thanks for posting it @amarbijay, it just works - your code should be the default example.
Great example
At last I can create a node with curl, I'm sure there are many example that works, I never can't add to the header the token, the only way to do it, was the great amarbijay's example. I would like to show my code:
function _create_node($username, $fname, $lname, $mail, $country, $bdate){
$request_url = 'http://127.0.0.1/proyect/end_point/user/login';
$type = 'article';
$user = 'zp-user';
$pass = '123';
$user_data = array(
'username' => $user,
'password' => $pass,
);
$user_data = http_build_query($user_data);
$curl = curl_init($request_url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json'));
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data);
curl_setopt($curl, CURLOPT_HEADER, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
curl_setopt($curl, CURLOPT_COOKIESESSION, true);
$response = curl_exec($curl);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($http_code == 200) {
$logged_user = json_decode($response);
}
else {
$http_message = curl_error($curl);
die($http_message);
}
curl_close($curl);
$request_url = 'http://127.0.0.1/proyect/end_point/node';
$node_data = array(
'title' => $username,
'type' => $type,
'field_name_zp[und][0][value]' => $fname,
'field_lastname_zp[und][0][value]' => $lname,
'field_country_zp[und][0][value]' => $country,
'field_bday_zp[und][0][value]' => $bdate,
'field_country_zp[und][0][value]' => $country,
'field_email_zp[und][0][value]' => $mail,
);
$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', 'X-CSRF-Token: ' . $logged_user->token));
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $node_data);
curl_setopt($curl, CURLOPT_HEADER, FALSE);
curl_setopt($curl, CURLOPT_COOKIE, "$cookie_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);
if ($http_code == 200) {
$node = json_decode($response);
}
else {
$http_message = curl_error($curl);
die($http_message);
}
}
@amarbijay Worked For us : Code written perfectly.
Thanks for support.
Error 404
thanks for this example , I have used the same example to fetch user friends from drupal website but its returning me 404 , Please help. I am getting the logged user session id and name but when I hit using the same then I get 404
Please help.
thanks,