Saving a Node Remotely using Services and API Key Authentication

0 min read

Steve Krueger

The social web is becoming more and more distributed with the ability to hook into external APIs to post data and information to your favourite sites. In this tutorial we'll explore the Drupal Services module using XML-RPC to post content to a host website - remotely.

Note: This tutorial will assume that you have 2 Drupal websites that are currently running. One of these will act as the host (running Services module) while the other will act as the slave which will be remotely communicating with the host. During this tutorial, we will refer to the host as "Host" and the slave as "Slave".

First thing's first.

Grab a copy of the latest version of the Services module and enable it on the Host. We'll also need to enable the following sub-modules:

Services Key Authentication XMLRPC Server Node Service

Setup our API Keys

On the Host site, navigate to hostsite.com/admin/build/services/keys. Enter in your "Application Title" and for "Allowed Domain" enter in your Slave's top level domain name. (ie: slavesite.com). Under "Method Access", select "node.save" and click on "Create Key" to submit the form. For this tutorial we will only be saving a node to the Host. If you require additional methods, select the appropriate items.

Once your key has been setup, we'll navigate to the "Settings" page at hostsite.com/admin/build/services/settings. For "Authentication Module" select "Key authentication" and insure that "Use keys" has been checked. For this tutorial, we will only be using API Keys for authentication, so let's un-check "Use sessid" and click "Save Settings" to save the form.

Setting up our Slave

We will be using Drupal's built in xmlrpc() function to remotely connect and communicate with our Host. All functionality of the remote communication will reside in code, so let's start off by creating a new module and enable it on the Slave.

Files that you will need for your "Remote" module:

remote (this is a folder) remote.info remote.module

Contents of Files


name = "Remote" description = "Slave remote communicator using XMLRPC." core = 6.x


$server, 'hash' => $hash, 'domain' => $domain, 'timestamp' => $timestamp, 'nonce' => $nonce, ); return $return; } /* * Remote talking. Formalize our data to send/receive to/from the Host. * @method - The name of the callmethod to use when retrieving/sending data. ex: "node.save" * @data - formalized expected data. */ function remote_talk($method = '', $data) { $values = remote_call($method); // Get a node from the remote server and pass in the required fields see: http://api.drupal.org/api/function/xmlrpc $xmlrpc_result = xmlrpc($values['server'], $method, $values['hash'], $values['domain'], $values['timestamp'], $values['nonce'], $data); if ($xmlrpc_result === FALSE) { return xmlrpc_error(); } else { return $xmlrpc_result; } }

Both of these functions will act as our method of calling Host to retrieve or send data - in our case, send. I've commented the code along the way but if there are any questions, please ask in the comments below.

Create our Form for Submission

In our remote.module we'll also include a form that will be presented to the user for them to fill out. The fields that they'll enter will be submitted to our Host to create a node. Add this function to our remote.module.

/* * Create issue form. */ function remote_create_form(&$node, $form_state = '') { // Title of the new node textfield. $form['title'] = array( '#type' => 'textfield', '#title' => t('Title'), '#required' => TRUE, ); // Body of the new node textarea. $form['body'] = array( '#type' => 'textarea', '#title' => t('Description'), '#rows' => 10, '#required' => TRUE, ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Submit'), ); // Submit handler where we will pass on our submitted values to Host. $form['#submit'][] = 'remote_create_form_submit'; return $form; }

Now that we've setup our form, we'll want to add the submit handler function that we're calling in remote_create_form().

function remote_create_form_submit($form_values, $form_state) { // Formalize the node array. $node['title'] = $form_values['title']['#value']; // These are the values that have been passed on from the form submit. $node['body'] = $form_values['body']['#value']; // These are the values that have been passed on from the form submit. $node['type'] = 'page'; // a valid content type on Host. $node['created'] = time(); $node['status'] = 1; $node['promote'] = 0; $node['sticky'] = 0; $node['format'] = 1; $node['name'] = 'ValidUsername'; // Note: We'll replace this with a valid username that resides on the Host site. // Create node obj to send through Services. $node = node_submit($node); // Send off to our XMLRPC call with the proper call method. $return = remote_talk('node.save', $node); // Error reporting. if($return->is_error) { drupal_set_message(t('There was an error') . ': ' . t($return->message) . '.', 'error'); } else { drupal_set_message(t('Thank you for your submission.')); } }

Now that everything is in place and working (crosses fingers), we'll want to show this form to our users so they'll be able to post a node to Host. Anywhere on your site, you can call drupal_get_form('remote_create_form') to render the form that we created. Test out the functionality and have some fun!

For additional resources and information, check out the Services Handbook page on Drupal.org.