<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Mariano Guerra's Log (Posts about gae)</title><link>http://marianoguerra.org/</link><description></description><atom:link href="http://marianoguerra.org/categories/gae.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Mon, 18 Nov 2024 17:56:30 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>PubHubSubBub Developer Tutorial</title><link>http://marianoguerra.org/posts/201103pubhubsubbub-developer-tutorial/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;p&gt;Note: the project and this document are hosted here: &lt;a href="https://github.com/marianoguerra/pshb-example"&gt;https://github.com/marianoguerra/pshb-example &lt;/a&gt;improvements and corrections are welcome!&lt;br&gt;&lt;br&gt;welcome, this document contains an example application written in python that will help you play with a pshb (pubsubhubbub from now on) hub and an application that publishes its content to it.&lt;br&gt;&lt;br&gt;this guide explains how to install a pubsubhubbub server in your computer so you can play with it, normally on a web application you would use a pshb compatible server like:&lt;br&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;official pshb hub on app engine: &lt;a href="http://pubsubhubbub.appspot.com/"&gt;http://pubsubhubbub.appspot.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;superfeedr hub: &lt;a href="http://superfeedr.com/"&gt;http://superfeedr.com/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="section" id="requirements"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Requirements&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;&lt;blockquote&gt;&lt;ul class="simple"&gt;&lt;li&gt;python &amp;gt;= 2.5 (I'm using 2.6.1)&lt;/li&gt;&lt;li&gt;git (for the example)&lt;/li&gt;&lt;li&gt;subversion (to download pshb code)&lt;/li&gt;&lt;li&gt;bash or similar shell to run the scripts&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;div class="section" id="installing"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Installing&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;&lt;pre class="literal-block"&gt;git clone https://github.com/marianoguerra/pshb-example.git&lt;br&gt;cd pshb-example&lt;br&gt;bash setup.sh&lt;/pre&gt;&lt;pre class="literal-block"&gt;&lt;/pre&gt;the first command will fetch the project from github, the third one will get some libraries needed for the example to run.&lt;br&gt;&lt;br&gt;note: answer "y" to sammy and "n" to all the other questions that the script does (we don't need those libraries)&lt;/div&gt;&lt;div class="section" id="running"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Running&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;now we will start the example application called pleinu twice (so we can test the communication using the hub) and we will start a local pshb hub.&lt;br&gt;&lt;br&gt;open 3 terminals and run one comment on each one:&lt;br&gt;&lt;br&gt;&lt;pre class="literal-block"&gt;google_appengine/dev_appserver.py src/ -p 8000 --datastore_path=/tmp/tubes1&lt;br&gt;google_appengine/dev_appserver.py src/ -p 8001 --datastore_path=/tmp/tubes2&lt;br&gt;google_appengine/dev_appserver.py pubsubhubbub/hub/&lt;/pre&gt;&lt;pre class="literal-block"&gt;&lt;/pre&gt;this commands asume that you are at the root of the pshb-example folder.&lt;/div&gt;&lt;div class="section" id="playing"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Playing&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;open a browser tabs pointing to:&lt;br&gt;&lt;blockquote&gt;&lt;ul class="simple"&gt;&lt;li&gt;&lt;a class="reference external" href="http://localhost:8000/"&gt;http://localhost:8000/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;click the signup link and create a new user.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="121" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-1.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;I will create one called spongebob, you will have to change the username whenever you see it.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="119" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-2.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;after the signup process click the login button and enter the user and password you just entered.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="62" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-3.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;create a message and click send, the message should appear below.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="90" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-4.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="116" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-5.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;now go to &lt;a class="reference external" href="http://localhost:8000/atom/messages/from/spongebob/"&gt;http://localhost:8000/atom/messages/from/spongebob/&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="233" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-6.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;you should see an atom feed with the message you just created.&lt;/div&gt;&lt;div class="section" id="publishing"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Publishing&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;now that we have a page that generates information we need to publish it on the hub.&lt;br&gt;&lt;br&gt;open a tab in your browser pointing to &lt;a class="reference external" href="http://localhost:8080/"&gt;http://localhost:8080/&lt;/a&gt; and click on the publish link near the bottom.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-7.png" width="317"&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="publishing"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-8.png" width="300"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;if you get an error remove the s from the https protocol in the address bar and refresh.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="88" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-9.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;on the Topic field enter the url to the atom feed we saw before: &lt;a class="reference external" href="http://localhost:8000/atom/messages/from/spongebob/"&gt;http://localhost:8000/atom/messages/from/spongebob/&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="146" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-10.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;and click Publish, the page wont change, that's ok.&lt;/div&gt;&lt;div class="section" id="subscribing"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Subscribing&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;now we need to subscribe one user from the other site (&lt;a class="reference external" href="http://localhost:8001/"&gt;http://localhost:8001/&lt;/a&gt;) to the messages sent by our user.&lt;br&gt;&lt;br&gt;go to &lt;a class="reference external" href="http://localhost:8001/"&gt;http://localhost:8001/&lt;/a&gt; and create another user, I will call it patrick&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-11.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="121" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-11.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;in the main page of the hub (&lt;a class="reference external" href="http://localhost:8080/"&gt;http://localhost:8080/&lt;/a&gt;) click on the subscribe like near the bottom&lt;br&gt;&lt;br&gt;enter &lt;a class="reference external" href="http://localhost:8001/p/notify/patrick/"&gt;http://localhost:8001/p/notify/patrick/&lt;/a&gt; on the Callback field (change patrick for your username if you used another one) enter &lt;a class="reference external" href="http://localhost:8000/atom/messages/from/spongebob/"&gt;http://localhost:8000/atom/messages/from/spongebob/&lt;/a&gt; on the Topic field (change spongebob for your username if you used another one)&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-12.png" width="308"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;click the "Do it" button, the page won't change, that's ok.&lt;/div&gt;&lt;div class="section" id="sending-a-message"&gt;&lt;h1&gt; &lt;/h1&gt;&lt;h1&gt;Sending a message&lt;/h1&gt;&lt;h1&gt; &lt;/h1&gt;Go to &lt;a class="reference external" href="http://localhost:8000/"&gt;http://localhost:8000/&lt;/a&gt; (login if you closed it) and send a message.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-13.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-13.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt; Now go to &lt;a class="reference external" href="http://localhost:8001/"&gt;http://localhost:8001/&lt;/a&gt; and refresh the page, you should see the messages published by the user in the other site.&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="214" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-16.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;&lt;div class="note"&gt;&lt;div class="first admonition-title"&gt;&lt;b&gt;Note&lt;/b&gt;&lt;/div&gt;&lt;div class="first admonition-title"&gt;&lt;br&gt;&lt;/div&gt;&lt;i&gt; &lt;/i&gt;&lt;br&gt;&lt;div class="last"&gt;&lt;i&gt;to make it work and avoid an exception I had to add a  return statement at the beginning of the log_message function at  google_appengine/google/appengine/tools/dev_appserver.py&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;br&gt;if you get that exception like this:&lt;br&gt;&lt;br&gt;&lt;pre class="literal-block"&gt;in log_request&lt;br&gt;    self.requestline, str(code), str(size))&lt;br&gt;  File "/home/asd/pubsubhubbub/pshb/google_appengine/google/appengine/&lt;br&gt;tools/dev_appserver.py", line 3314, in log_message&lt;br&gt;    if self.channel_poll_path_re.match(self.path):&lt;br&gt;AttributeError: DevAppServerRequestHandler instance has no attribute&lt;br&gt;'path'&lt;/pre&gt;&lt;pre class="literal-block"&gt;&lt;/pre&gt;edit the function to look like this:&lt;br&gt;&lt;pre class="literal-block"&gt; &lt;/pre&gt;&lt;pre class="literal-block"&gt;def log_message(self, format, *args):&lt;br&gt;  """Redirect log messages through the logging module."""&lt;br&gt;  return&lt;br&gt;  if self.channel_poll_path_re.match(self.path):&lt;br&gt;    logging.debug(format, *args)&lt;br&gt;  else:&lt;br&gt;    logging.info(format, *args)&lt;br&gt;&lt;/pre&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="142" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-15.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;you will have to set write permissions to the file to save it (chmod u+w dev_appserver.py)&lt;br&gt;&lt;br&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="137" src="https://github.com/marianoguerra/pshb-example/raw/master/doc/img/pshb-14.png" width="320"&gt;&lt;/a&gt;&lt;/div&gt;&lt;br&gt;&lt;br&gt;you will have to restart the pshb server:&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;pre class="literal-block"&gt;google_appengine/dev_appserver.py pubsubhubbub/hub/&lt;/pre&gt;&lt;/div&gt;</description><category>app engine</category><category>flask</category><category>gae</category><category>google</category><category>google app engine</category><category>pshb</category><category>pubsubhubbub</category><category>python</category><category>tutorial</category><guid>http://marianoguerra.org/posts/201103pubhubsubbub-developer-tutorial/</guid><pubDate>Tue, 15 Mar 2011 02:22:00 GMT</pubDate></item><item><title>nuevo intento de viejo proyecto</title><link>http://marianoguerra.org/posts/201003nuevo-intento-de-viejo-proyecto/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;p&gt;queres probar algo nuevo? tenes algun lugar para recomendar? ayudame a cargar datos http://pleinu.appspot.com (consejos/quejas bienvenidas)&lt;br&gt;&lt;br&gt;esta vez empieza desde lo basico y se arma con tu feedback&lt;br&gt;&lt;br&gt;para los nionios como yo, esta hecho en python sobre appengine usando tubes*&lt;br&gt;&lt;br&gt;* http://a-series-of-tubes.appspot.com/ y http://github.com/marianoguerra/tubes&lt;/p&gt;</description><category>gae</category><category>pleinu</category><category>python</category><category>tubes</category><guid>http://marianoguerra.org/posts/201003nuevo-intento-de-viejo-proyecto/</guid><pubDate>Fri, 12 Mar 2010 14:32:00 GMT</pubDate></item><item><title>Pubsubhubbub developer's guide</title><link>http://marianoguerra.org/posts/200909pubsubhubbub-developers-guide/</link><dc:creator>Mariano Guerra</dc:creator><description>&lt;h2&gt;&lt;a name="naming_conventions"&gt;naming conventions&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a name="naming_conventions"&gt;pshb/PSHB = pubsubhubbub &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="naming_conventions"&gt;gae/GAE = Google App Engine &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="naming_conventions"&gt;things that start with "$" are bash commands &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="naming_conventions"&gt;things that start with "!" are important notes &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;a name="create_directory_to_hold_all_the_content_of_this_tutorial"&gt;create directory to hold all the content of this tutorial&lt;/a&gt;&lt;/h2&gt;&lt;pre class="prettyprint"&gt;&lt;a name="create_directory_to_hold_all_the_content_of_this_tutorial"&gt;&lt;span class="pln"&gt;$ mkdir pshb&lt;br&gt;$ cd pshb&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;h2&gt;&lt;a name="download_Google_App_Engine_SDK"&gt;download Google App Engine SDK&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="download_Google_App_Engine_SDK"&gt;&lt;strong&gt;!&lt;/strong&gt; pshb trunk needs the latest version of GAE (1.2.4 as of today) to work, but &lt;strong&gt;!&lt;/strong&gt; the download page display an older version &lt;/a&gt;&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;a name="download_Google_App_Engine_SDK"&gt;&lt;span class="pln"&gt;$ wget http&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//googleappengine.googlecode.com/files/google_appengine_1.2.4.zip&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;$ unzip google_appengine_1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="lit"&gt;2.4&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;zip&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;p&gt;&lt;a name="download_Google_App_Engine_SDK"&gt;&lt;strong&gt;!&lt;/strong&gt; GAE needs python 2.5 in order to work, if you have an older or newer version of python install python 2.5 (OS and distro dependent, wont be covered here) &lt;/a&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name="download_the_latest_version_of_pshb"&gt;download the latest version of pshb&lt;/a&gt;&lt;/h2&gt;&lt;pre class="prettyprint"&gt;&lt;a name="download_the_latest_version_of_pshb"&gt;&lt;span class="pln"&gt;$ svn checkout http&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//pubsubhubbub.googlecode.com/svn/trunk/ pubsubhubbub&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;h2&gt;&lt;a name="start_pshb"&gt;start pshb&lt;/a&gt;&lt;/h2&gt;&lt;pre class="prettyprint"&gt;&lt;a name="start_pshb"&gt;&lt;span class="pln"&gt;$ python2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pln"&gt; google_appengine&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;dev_appserver&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;py pubsubhubbub&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;hub&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;p&gt;&lt;a name="start_pshb"&gt;&lt;strong&gt;!&lt;/strong&gt; note the python2.5 command &lt;/a&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name="check_that_the_hub_started"&gt;check that the hub started&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="check_that_the_hub_started"&gt;type &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8080&lt;/span&gt; on your browser, you should see something like: &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="check_that_the_hub_started"&gt;&lt;i&gt;Welcome to the demo &lt;span style="border-bottom: 1px dotted black;"&gt;PubSubHubbub&lt;/span&gt; reference Hub server!&lt;/i&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="check_that_the_hub_started"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="check_that_the_hub_started"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqrdHFQ2i6I/AAAAAAAAGxs/kPxuBPwJ6Nc/s1600-h/pshb0.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqrdHFQ2i6I/AAAAAAAAGxs/kPxuBPwJ6Nc/s320/pshb0.png" alt="" id="BLOGGER_PHOTO_ID_5380355818589162402" border="0"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;&lt;a name="download_the_example"&gt;download the example&lt;/a&gt;&lt;/h2&gt;&lt;pre class="prettyprint"&gt;&lt;a name="download_the_example"&gt;&lt;span class="com"&gt;# we will need to fetch the tubes library and the example that we will be using.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;$ git clone git&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//github.com/marianoguerra/tubes.git&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span class="com"&gt;# now we will start the example&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;$ cd tubes&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;ihasfriendz&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;$ python main&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;py&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;p&gt;&lt;a name="download_the_example"&gt;we should see something like: &lt;/a&gt;&lt;/p&gt;&lt;pre class="prettyprint"&gt;&lt;a name="download_the_example"&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;*&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Running&lt;/span&gt;&lt;span class="pln"&gt; on http&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//0.0.0.0:8081/&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;/span&gt;&lt;span class="pun"&gt;*&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Restarting&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;with&lt;/span&gt;&lt;span class="pln"&gt; reloader&lt;/span&gt;&lt;span class="pun"&gt;...&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;&lt;h3&gt;&lt;a name="components_used_by_the_example"&gt;components used by the example&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a name="components_used_by_the_example"&gt;   &lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a name="components_used_by_the_example"&gt;werkzeug: &lt;span style="border-bottom: 1px dotted black;"&gt;http://werkzeug.pocoo.org&lt;/span&gt; &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="components_used_by_the_example"&gt;jquery: &lt;span style="border-bottom: 1px dotted black;"&gt;http://jquery.com&lt;/span&gt; &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="components_used_by_the_example"&gt;tubes: &lt;span style="border-bottom: 1px dotted black;"&gt;http://github.com/marianoguerra/tubes/tree/master&lt;/span&gt; &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="components_used_by_the_example"&gt;pubsubhubbub_publish.py: from pshb &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a name="components_used_by_the_example"&gt;feedformatter.py: &lt;span style="border-bottom: 1px dotted black;"&gt;http://code.google.com/p/feedformatter/&lt;/span&gt; &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;&lt;a name="publish_the_feed_to_the_hub"&gt;publish the feed to the hub&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="publish_the_feed_to_the_hub"&gt;go to the following URL on your browser: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8080/publish&lt;/span&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="publish_the_feed_to_the_hub"&gt;on the &lt;i&gt;Topic&lt;/i&gt; field enter: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/atom/stream/_MYUSER_&lt;/span&gt; and click publish &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="publish_the_feed_to_the_hub"&gt;&lt;strong&gt;!&lt;/strong&gt; if everything goes OK, then you wont notice anything on the page, that's ok, browsers act that way to 204 responses &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="publish_the_feed_to_the_hub"&gt;&lt;strong&gt;!&lt;/strong&gt; &lt;i&gt;MYUSER&lt;/i&gt; is a placeholder for the user you will use to post notices on the test app later (for example &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/atom/stream/marianoguerra&lt;/span&gt;) &lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XkKIWh0VZYk/SqrdHbMyTDI/AAAAAAAAGx0/HU3XaAhjP_w/s1600-h/pshb1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://4.bp.blogspot.com/_XkKIWh0VZYk/SqrdHbMyTDI/AAAAAAAAGx0/HU3XaAhjP_w/s320/pshb1.png" alt="" id="BLOGGER_PHOTO_ID_5380355824477686834" border="0"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;&lt;a name="subscribing_to_the_hub"&gt;subscribing to the hub&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="subscribing_to_the_hub"&gt;go to the following URL on your browser: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8080/subscribe&lt;/span&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="subscribing_to_the_hub"&gt;on the &lt;i&gt;Callback&lt;/i&gt; field enter: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/callback&lt;/span&gt; on the &lt;i&gt;Topic&lt;/i&gt; field enter: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/atom/stream/_MYUSER_&lt;/span&gt; on the &lt;i&gt;Verify token&lt;/i&gt; field enter something random like: &lt;i&gt;iwantmahcookie&lt;/i&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="subscribing_to_the_hub"&gt;&lt;strong&gt;!&lt;/strong&gt; &lt;i&gt;MYUSER&lt;/i&gt; is a placeholder for the user you will use to post notices on the test app later (for example &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/atom/stream/marianoguerra&lt;/span&gt;) &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="subscribing_to_the_hub"&gt;click &lt;i&gt;Do it&lt;/i&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="subscribing_to_the_hub"&gt;&lt;strong&gt;!&lt;/strong&gt; if everything goes OK, then you wont notice anything on the page, that's OK, browsers act that way to 204 responses &lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_XkKIWh0VZYk/SqrdHx3cWDI/AAAAAAAAGx8/V4UrVzmx1Tc/s1600-h/pshb2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://4.bp.blogspot.com/_XkKIWh0VZYk/SqrdHx3cWDI/AAAAAAAAGx8/V4UrVzmx1Tc/s320/pshb2.png" alt="" id="BLOGGER_PHOTO_ID_5380355830562183218" border="0"&gt;&lt;/a&gt;&lt;h2&gt;&lt;a name="create_some_content"&gt;create some content&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="create_some_content"&gt;go to the following URL on your browser: &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/files/index.html&lt;/span&gt; &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="create_some_content"&gt;post some content on the form, use the user you used as &lt;i&gt;MYUSER&lt;/i&gt; &lt;/a&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqrdIRtBMoI/AAAAAAAAGyE/hOtiESEaaHY/s1600-h/pshb3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqrdIRtBMoI/AAAAAAAAGyE/hOtiESEaaHY/s320/pshb3.png" alt="" id="BLOGGER_PHOTO_ID_5380355839108395650" border="0"&gt;&lt;/a&gt;&lt;a name="create_some_content"&gt;&lt;br&gt;you can check that the item was posted going manually to &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/atom/stream/_MYUSER_&lt;/span&gt;, you should see an atom feed there&lt;br&gt;&lt;/a&gt;&lt;p&gt;&lt;a name="create_some_content"&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqrdJC1gwRI/AAAAAAAAGyM/vKPiADfZpLI/s1600-h/pshb4.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqrdJC1gwRI/AAAAAAAAGyM/vKPiADfZpLI/s320/pshb4.png" alt="" id="BLOGGER_PHOTO_ID_5380355852297355538" border="0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name="manually_processing_the_tasks"&gt;manually processing the tasks&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;when running the hub on the dev server we have to run the task queues by hand, to do that go to &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8080/_ah/admin/queues&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;&lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_XkKIWh0VZYk/Sqrd_5aSiyI/AAAAAAAAGyU/pjEz8TOZXWc/s1600-h/pshb5.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://2.bp.blogspot.com/_XkKIWh0VZYk/Sqrd_5aSiyI/AAAAAAAAGyU/pjEz8TOZXWc/s320/pshb5.png" alt="" id="BLOGGER_PHOTO_ID_5380356794660064034" border="0"&gt;&lt;/a&gt;&lt;br&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;on the &lt;i&gt;Tasks in Queue&lt;/i&gt; column of the &lt;i&gt;feed-pulls&lt;/i&gt; you should see a number different than 0 (that is the number of messages you created since the last execution of that task). &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;click on the &lt;i&gt;feed-pulls&lt;/i&gt; link, there click on the &lt;i&gt;run&lt;/i&gt; button. &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;when we run the feed pulls task, we tell pshb to fetch th&lt;/a&gt;&lt;a name="manually_processing_the_tasks"&gt;e feeds that have new content (the ones that did a post to the hub to inform that there is new content)&lt;br&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqreATS1_OI/AAAAAAAAGyc/loOLwdvXcSk/s1600-h/pshb6.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://3.bp.blogspot.com/_XkKIWh0VZYk/SqreATS1_OI/AAAAAAAAGyc/loOLwdvXcSk/s320/pshb6.png" alt="" id="BLOGGER_PHOTO_ID_5380356801608154338" border="0"&gt;&lt;/a&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;&lt;strong&gt;!&lt;/strong&gt;  on production hubs this tasks are done autom&lt;/a&gt;&lt;a name="manually_processing_the_tasks"&gt;atically &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;now we go again to the &lt;i&gt;Task Queues&lt;/i&gt; page, th&lt;/a&gt;&lt;a name="manually_processing_the_tasks"&gt;ere the &lt;i&gt;event-delivery&lt;/i&gt; queue should have a number different than 0 (the number of messages that are pending to be sent to the subscribers), we click on the &lt;i&gt;event-delivery&lt;/i&gt; and then we click on the &lt;i&gt;run&lt;/i&gt; button. &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="manually_processing_the_tasks"&gt;when we run the event delivery task, we tell pshb to do a POST on every callback url registered for the feeds that were fetched on the &lt;i&gt;feed-pulls&lt;/i&gt; task. &lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqreA9bViFI/AAAAAAAAGyk/TOOj_6tdoJ8/s1600-h/pshb7.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqreA9bViFI/AAAAAAAAGyk/TOOj_6tdoJ8/s320/pshb7.png" alt="" id="BLOGGER_PHOTO_ID_5380356812918065234" border="0"&gt;&lt;/a&gt;&lt;h2&gt;&lt;a name="seeing_it_work"&gt;seeing it work&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;a name="seeing_it_work"&gt;now that we created a feed, informed the hub that we had new content, the hub fetched the content and sent it to the callback, we want to see this content, for this go with your browser to &lt;span style="border-bottom: 1px dotted black;"&gt;http://localhost:8081/new-notices/&lt;/span&gt;, you will see the notices that pshb posted back to you the last time. &lt;/a&gt;&lt;/p&gt;&lt;br&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqreBWaXNCI/AAAAAAAAGys/wxGClI7Q2S0/s1600-h/pshb8.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 200px;" src="http://1.bp.blogspot.com/_XkKIWh0VZYk/SqreBWaXNCI/AAAAAAAAGys/wxGClI7Q2S0/s320/pshb8.png" alt="" id="BLOGGER_PHOTO_ID_5380356819624866850" border="0"&gt;&lt;/a&gt;&lt;br&gt;&lt;p&gt;&lt;a name="seeing_it_work"&gt;&lt;strong&gt;!&lt;/strong&gt; if you refresh the page you will notice that the messages aren't there anymore, that's because the example stores the new messages in a Queue that is flushed when the request for new notices is made, in this way you can see only the new messages. &lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a name="seeing_it_work"&gt;&lt;strong&gt;!&lt;/strong&gt; the example stores all the information on global variables on main.py (this is to make the example simpler), so every time you change something on main.py and save the server will reload the changes and all the data will disappear. &lt;/a&gt;&lt;/p&gt;&lt;h2&gt;&lt;a name="for_lazy_people"&gt;for lazy people&lt;/a&gt;&lt;/h2&gt;&lt;pre class="prettyprint"&gt;&lt;a name="for_lazy_people"&gt;&lt;span class="com"&gt;#!/usr/bin/env sh&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span class="com"&gt;# create the example directory&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;mkdir pshb&lt;br&gt;cd pshb&lt;br&gt;&lt;br&gt;CWD&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;pwd&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;EXAMPLE&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt;$CWD&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;tubes&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="pln"&gt;ihasfriendz&lt;br&gt;&lt;br&gt;wget http&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//googleappengine.googlecode.com/files/google_appengine_1.2.4.zip&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;unzip google_appengine_1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="lit"&gt;2.4&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;zip&lt;br&gt;&lt;br&gt;svn checkout http&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//pubsubhubbub.googlecode.com/svn/trunk/ pubsubhubbub&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span class="com"&gt;# we will need to fetch the tubes library and the example that we will be using.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;git clone git&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//github.com/marianoguerra/tubes.git&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span class="com"&gt;# now we will start the example&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;&lt;br&gt;echo &lt;/span&gt;&lt;span class="str"&gt;"run \"cd $EXAMPLE; python main.py\" on a shell to run the example"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br&gt;echo &lt;/span&gt;&lt;span class="str"&gt;"run \"cd $PWD; python2.5 google_appengine/dev_appserver.py pubsubhubbub/hub/\" on a shell to run the hub"&lt;/span&gt;&lt;/a&gt;&lt;/pre&gt;</description><category>gae</category><category>phsb</category><category>pubsubhubbub</category><category>python</category><category>tubes</category><guid>http://marianoguerra.org/posts/200909pubsubhubbub-developers-guide/</guid><pubDate>Sat, 12 Sep 2009 00:00:00 GMT</pubDate></item></channel></rss>