Drupal Services Module

Déja Augustine's picture

Drupal is an extremely powerful and flexible content management system, and is a very strong foundation for a data-driven website. However, there are times when a solitary website just isn't enough -- for example you may want to have one main site and a number of affiliated sites, you may want to write a stand-alone application that can interact with your Drupal site, or you may want to share data between a Drupal site and a non-Drupal site. Situations like this call for a web service!

A web service is typically an API (application programming interface) that is hosted on a web server and exposed to the internet. One shining example of web services in our daily lives occurs every time you click the Submit button in an online shopping cart. A web service is responsible for telling the vendor that your credit card is valid and has enough room for you to make your purchase. Web services are also used to get your shipping quotes and reserve your tracking number.

The long and the short of it is that web services let websites talk to websites, websites talk with applications, and applications talk to applications.

Now, there are a number of different web service protocols (RPC, SOAP, AMF, REST, etc.). One of the drawbacks to web services is that they tend to be tied to a specific protocol, which means that you have to package up whatever data you wish to send to a web service in the protocol expected by the web service. If you are consuming multiple web services, it's quite possible that you'd have to package your data several different ways. To use the ecommerce example from above, you may have to package your order information (number of packages, each package's weight, source and destination addresses, etc.) for a SOAP-based shipping quote web service, and the customer's payment information for a REST-based credit card authorization service. This creates a lot of unnecessary complication in the world of web service consumption.

With all this in mind, when you sit down to write your own web service, where do you begin? What protocol should you use? How are you going to make the great behemoth of possibility that is Drupal available as a web service without sacrificing all that great power and flexibility by hard-coding your service to serve up only certain types of nodes and fields?

The beautiful answer is you don't have to think about any of that.

Enter the Services module. (http://drupal.org/project/services)

Services is a web service layer for Drupal that lets you check a few boxes and turn your Drupal website into a full-blown web service. In the Drupal tradition, Services is flexible and extensible. It separates the protocol used to transmit the data from the api that drives it. Out of the box, it contains the XML-RPC server module, but at the time of this writing there are modules to add JSON, JSON-RPC, REST, SOAP, and AMF compatibility. Each server module adds its own path. Changing protocols is as easy as changing the URL that the consuming application uses to connect. You can also easily write your own server module to define your own protocol or support one that does not already exist.

http://www.example.com/services/xmlrpc
http://www.example.com/services/json-rpc
http://www.example.com/services/super-awesome
etc.

The Server module also comes with a number of included services: node, comment, file, menu, search, system, taxonomy, user, views, and node_resource. Each service provides a number of methods, such as user.login, node.get, comment.save, taxonomy.selectNodes, etc. Using these services, you could write a stand-alone application that can sign in to your drupal site (user.login), read a node (node.get) and post a comment (comment.save) without ever having to crack open a web browser or parse a single line of HTML.

Just as with the protocols, adding your own services is very simple and straightforward. The Services module uses the protocol server module to parse the incoming data and then presents the data to your service module in a predictable, documented format. This means that you can write your custom service and not only will it be able to consumed simultaneously via SOAP, RPC, and SUPERawesome (your custom protocol), but it will also be able to consumed via protocols that have not even yet been defined.

In addition to the API, the Services module also provides a handy UI that lets you test any exposed methods by providing data directly into a form. Method help and argument description text can be provided by the service developer, and is displayed on this form.

Finally Services provides a number of options on the security front. If you don't feel comfortable opening up your website to any old web service, you can enable API Key Authentication which requires that a pre-created set of credentials be provided or your request will be rejected. You can also enable Session-based authentication requiring a valid session id to be presented with each call to verify that you're still the same consumer who connected/logged in previously. Finally, each service method can even provide its own access check so you could potentially have the ability to define which specific methods a particular role has access to.

I'll close out this exploration with a code sample showing you how little it takes to create a custom service module.

ExampleModule.info
name = "Example Service Module"
description = "Demonstrates creating a new service module"
package = "Services - services"
dependencies[] = services
core = "6.x"

ExampleModule.module

  1. function ExampleModule_disable() {
  2. cache_clear_all('services:methods', 'cache');
  3. }
  4.  
  5. function Example_enable() {
  6. cache_clear_all('services:methods', 'cache');
  7. }
  8.  
  9. function ExampleModule_service() {
  10.  
  11. return array(
  12. '#method' => 'example.echo',
  13. '#callback' => 'ExampleModule_echo',
  14. '#args' => array(
  15. '#name' => 'text',
  16. '#type' => 'string',
  17. '#optional' => TRUE,
  18. '#description' => t('Enter the string that the server should return.')
  19. ),
  20. '#return' => 'string',
  21. '#help' => t('Echos the provided string back to the consumer.')
  22. ),
  23. );
  24. }
  25.  
  26. function ExampleModule_echo($text = "") {
  27. global $user;
  28.  
  29. if($text == "")
  30. return services_error(t('There was no text provided to echo'), 404);
  31.  
  32. return sprintf("%s just wanted to say: %s", $user->name, $text);
  33. }

Comments

Roger's picture

Thanks for such an informative article.

Drupal design

Sharon's picture

I've been looking web service implementation to retrieve drupal themes from TotalTheme.com, similiar to Wordpress "Install theme" feature. Awesomeee. Thanks for making this available. The custom service module really helps.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockcode>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <blockcode>. The supported tag styles are: <foo>, [foo]. PHP source code can also be enclosed in <?php ... ?> or <% ... %>.

More information about formatting options

CAPTCHA
Are you a robot? We usually like robots, but not in our comments.
By submitting this form, you accept the Mollom privacy policy.