The full code for this sample is available at https://github.com/jcleblanc/programming-social-applications/tree/master/chapter_10/pubsubhubbub-publisher-python.
Now that we have looked at a publisher implementation in PHP, let’s explore the same implementation using Python for an alternate vantage point.
For this example, the classes that make up the publisher are stored in a file named publisher.py:
import re import urllib import urllib2 ''' ' Class: Publishing Error ' Description: Custom error class for publishing exceptions ''' class PublishError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) ''' ' Class: Publisher ' Description: Provides ability to publish updates for feeds ''' class Publisher: regex_url = re.compile('^https?://') #simple URL string validator #constructor that stores the hub for the publisher def __init__(self, hub): if self.regex_url.match(hub): self.hub = hub else: raise PublishError('Invalid hub URL supplied') #makes request to hub to update feeds def publish(self, feeds): #set the POST string mode post_string = 'hub.mode=publish' #add each feed as a URL in the POST string, unless invalid URL for feed in feeds: if self.regex_url.match(feed): post_string += '&hub.url=%s' % (urllib.quote(feed)) else: raise PublishError('Invalid feed URL supplied: %s' % (feed)) try: #make request to hub file = urllib2.urlopen(self.hub, post_string) return True except (IOError, urllib2.HTTPError), e: #process http conditions in 2xx range as valid if hasattr(e, 'code') and str(e.code)[0] == '2': return True #process alternative error conditions error = '' if hasattr(e, 'read'): error = e.read() raise PublishError('%s, Response: "%s"' % (e, error))
This file contains two classes,
PublishError
and Publisher
. The purpose of Publish
E
rror
is simply to provide a
custom exception class to push out exceptions in the
publisher flow.
The Publisher
class mirrors
that of the PHP example, providing us with a constructor and a method to
publish our feeds. Once a new instance of the class is instantiated, the
constructor will simply check that the hub URL provided is valid. If it
is, the URL will be stored; otherwise, an exception is thrown.
When we call the publish
method, we will start out by setting a base for the POST string that
will be sent with the publish request to the hub. The hub expects a
couple of parameters:
hub.mode
This should be set to publish
for the publishing
action.
hub.url
For each feed that should be updated, there should be a
hub.url
parameter.
We then loop through each feed provided in the feeds list. We
check to ensure that the feed is valid and, if so, append a new hub.url
parameter to the end of the POST
string. If the feed is invalid, an exception is thrown.
Last, we try to make a POST request to the hub URL, passing in the
POST string. If there were no errors produced, we simply return True
. If errors are produced, we check whether
the HTTP response was in the 2xx range. If so, we
treat this as a valid response. If not, we throw an appropriate
exception.
Now let’s see how we can use the Publisher
class:
from publisher import * #define hub and feeds hub = 'http://pubsubhubbub.appspot.com/' feeds = ['http://www.example.com/feed1.xml', 'http://www.example.com/feed2.xml', 'http://www.example.com/feed3.xml'] #create new publisher publisher = Publisher(hub) #publish feed updates: response == True on success response = publisher.publish(feeds) #print message on success if (response == True): print 'Content-Type: text/plain' print '' print 'Update successful'
We start the example by importing the class file and then defining
the hub URL and the URLs for the feeds that we want to publish updates
for. We then create a new instance of the
Publisher
class, passing in the hub
URL, and then call the publish
(...)
method,
passing in the feed list. If the response from that call is True
, then the process completed
successfully and we print out the appropriate message.
18.223.172.132