Creating weblogUpdates.ping SOAP web services with Rails

Posted by ryan
at 10:39 AM on Tuesday, November 22, 2005

I’ve recently had the occasion to work on both the client and server ends of implementing the weblogUpdates.ping SOAP call and thought it might be worthwhile to post the results here.

First, a little background. “weblogUpdates.ping” is a way for blogging software to notify aggregators that there’s been an update to the blog. If you use Technorati or blo.gs this is how your blogging package notifies the services when you post a new entry. The specification for this SOAP call is outlined here and here.

As you can see, it’s a pretty simple call. We need to make a SOAP call to the “weblogUpdates.ping” method with two string arguments, the title of the blog and the absolute URL of the blog – not the permalink of the new entry. (taken from technorati docs)

<?xml version="1.0"?>
<methodCall>
  <methodName>weblogUpdates.ping</methodName>
  <params>
    <param>
      <value>YOUR WEBLOG NAME HERE</value>
    </param>
    <param>
      <value>http://www.YOURWEBLOGURL.com/</value>
    </param>
  </params>
</methodCall>
So, on to implementing both sides of this in Ruby on Rails...

Let’s start with the client side, if you have a Rails app (such as a Rails blogger like Typo) that needs to send out a ping to Technorati or any other blog aggregator then you’ll need to send out this ping. This turns out to be quite simple, here’s the jist of the code (derived from Why’s example)

begin

  server = XMLRPC::Client.new2(URI.parse(endpoint_url).to_s)

  begin
    result = server.call("weblogUpdates.ping", blog_name,
                          blog_url)
  rescue XMLRPC::FaultException => e
    logger.error(e)
  end

rescue Exception => e
  logger.error(e)
end
Keep in mind this is a synchronous call – so if the aggregator is slow in responding it will hang your app. Some thought should be given to spawning the actual call in a new thread.

So what about when you’re writing a Rails app that serves as an aggregator that needs to receive these ping calls? It’s not as simple as sending the ping, but with Rails’ strong web services support it’s still quite easy. So here’s how you go about doing that:

  • Create the API class that defines what the call looks like:
    # In app/apis/blog_api.rb
    
    class BlogAPI < ActionWebService::API::Base
      inflect_names false
      api_method :ping,
                 :expects => [ {:name => :string}, {:url => :string} ]
    end
    
    Note that you have to set the “inflect_names” property to false since not doing so will cause the underlying SOAP method to be named “weblogUpdates.Ping”, which we don’t want. Also notice that we haven’t specified the full name of the call and have left off the “weblogUpdates” prefix. We’ll resolve this a few steps down by using the layered dispatching mode of Rails’ web services support which will bind a web service class to a specific name.
  • Next let’s create the actual web service class:
    # app/models/blog_api_service.rb
    
    class BlogAPIService < ActionWebService::Base
    
      web_service_api BlogAPI
    
      def ping(name, url)
        #Put your business logic here that handles incoming pings
      end
    end
    
    Pretty simple again, define a ping method that matches the BlogAPI method defined in the first step and add your business logic.
  • Now let’s wrap it all up with the controller that will handle the actual result:
    # app/controllers/blog_controller.rb
    
    class BlogController < ApplicationController
    
      web_service_scaffold :invoke
      web_service_dispatching_mode :layered
      web_service :weblogUpdates, BlogAPIService.new
    
    end
    
  • Now your SOAP weblogUpdates.ping service will be waiting at http://yourhostname/blog/api. To test it you can go to: http://yourhostname/blog/invoke.

And there you have it, sending and receiving the SOAP weblogUpdates.ping call. You can now write your own Rails version of Technorati and Moveable Type, so have at it.

Comments

Leave a response