1

Drupal 7.23 Services 7.x-3.5

I've followed the instructions for setting up Services module, including https://drupal.org/node/1699354. I got the endpoint setup successfully. I am able to retrieve index of nodes using ...endpoint/node and specific nodes using .../endpoint/node/#.

Now how can I create new nodes via Service through an URL? The Services manual gets really confusing at this point, is outdated and full of errors. The sample code they provide here https://drupal.org/node/1334758 ... am i supposed to put this in a custom module in order to be able to POST? If so, it turns my whole site blank right after adding this line:

// cURL 
$curl = curl_init($request_url);

Also, there's an issue with CSRF validation, as showing in the Firefox Poster tool. The Services forum is a madhouse so I come here in hopes that someone can guide me in the right direction. What other modules do I need to get this to work? Why does my site go blank after adding the code above?

A simple solution would be the following:

domain/endpoint?title=test&url=http%253A%252F%252Fwww.example.com

and produce a new node of nodetype with a title and URL.

3 Answers 3

1

In order to create the node you must use the POST HTTP request so you can't do something like domain/endpoint?title=test&url=http%253A%252F%252Fwww.example.com(it's GET HTTP request). You can do the following to solve your problems:

  1. First you need to make the Services 3.0 work with Firefox Poster tool. You can go Testing with REST Server for checking all the basic function in case you forgot to set the permissions or forgot to enable resources.
  2. After you find out how to communicate with Services 3.0. You can use drupal_http_request to build your own POST/GET HTTP request. An example will be here Making authenticated requests to REST Server.
2
  • Thanks. I had to learn how to use the Poster tool, fill in User Auth info, fill in the appropriate parameters, and finally click 'body from parameters'... then POST. I was able to create a post at the URL: my-domain/endpoint/node. No headers were required. I did not require any authentication like oAuth, however a username and password was required to post. As for the $curl issue, i will revisit that in another post. Thanks!
    – droopie
    Commented Oct 1, 2013 at 6:46
  • When we use Poster plugin of firefox actually we are using Session Authentication method. If we want to use OAuth authentication it will be a little complicate from we must generate token_request and token_access not just username/password
    – Stone Vo
    Commented Oct 1, 2013 at 7:06
1

Sample code provided there 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, try the following code once:

<?php

        // LOGIN AND GET CSRF TOKEN

        /*
            * Server REST - user.login
        */

        // REST Server URL
        $request_url = 'http://mysite....com/server/user/login.json';

        // User data
        $user_data = array(
        'username' => 'xxxx',
        'password' => 'xxxx',
        );
        $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);
        //print_r($response);
        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        //print "<br>".$http_code."</br>";
        // Check if login was successful
        if ($http_code == 200) {
            // Convert json response as array
            $logged_user = json_decode($response);
            //print_r($logged_user);

        }
        else {
            // Get error msg
            $http_message = curl_error($curl);
            die($http_message);
        }        


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

        //GET CSRF TOKEN
        curl_setopt_array($curl, array(
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_URL => 'http://mysite....com/services/session/token',
        ));
        curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); 
        // $csrf_token = curl_exec($curl);
        //print_r($csrf_token);

        $ret = new stdClass;

        $ret->response = curl_exec($curl);
        $ret->error    = curl_error($curl);
        $ret->info     = curl_getinfo($curl);


        //print_r($ret->response);
        $csrf_token = json_decode($ret->response)->token;


        /*
            * Server REST - node.create
        */

        // REST Server URL
        $request_url = 'http://mysite....com/server/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);

        // cURL
        $curl = curl_init($request_url);
        // Accept JSON response
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json', 'X-CSRF-Token: ' .$csrf_token));
        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);
        // use the previously saved session
        curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); 
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);

        $response = curl_exec($curl);
        print "<br><br>";
        print_r($response);
        $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);


    ?>
1
  • thanks for providing this code, although I was able to get the POST functioning without any additional modules. I did install some extra curl libraries in Apache server which i was missing, and could be the reason why my site went blank after any $curl statements. What is the reason for this code if HTTP Post is available without it? Thanks!
    – droopie
    Commented Oct 1, 2013 at 6:50
0

For some reason, the CRUD operation 'index - List all nodes' has to be checked in addition to 'Create a node' within the Resources menu, otherwise the CSRF validation issue remains.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.