Evolution of the Weblog APIs

By Sam Ruby, January 26, 2003.

This document explores as a fairly low level the evolution of the weblog APIs.  This topic was explored at a high level in Coping with Change.  Some familiarity with RSS, HTTP, and SOAP is helpful.  But mostly, a knowledge of XML as applied by the XML RPC specification is required.

Overview #

Two examples are used in this.  The first is an elided form of the first item in the documentation of the radioWeblogPost module:

<item>
  <description>...top secret report...</description>
  <pubDate>Sat, 01 Jun 2002 04:55:43 GMT</pubDate>
  <source url="http://partners.userland.com/nyt/nytHomepage.xml">New York Times: NYT HomePage</source>
</item> 

The second is a description of this essay itself, categorized into two categories:

<item>
  <description>Evolution of Weblog APIs</description>
  <link>http://www.intertwingly.net/stories/2003/01/26/evolve.html</link>
  <category>RSS</category>
  <category>XML-RPC</category>
</item>

Blogger API #

The Blogger API is popular for posting items to weblogs.  It was originally authored by Evan Williams and eagerly adopted by Userland.  To post the first example to a hypothetical weblog, you would sent the following:

<methodCall>
  <methodName>blogger.newPost</methodName>
  <params>
    <param>
      <value>mozblog</value>
    </param>
    <param>
      <value>0101679</value>
    </param>
    <param>
      <value>me</value>
    </param>
    <param>
      <value>gObBlEdYgOoK</value>
    </param>
    <param>
      <value>...top secret report...</value>
    </param>
    <param>
      <value>1</value>
    </param>
  <params>
</methodCall>

MetaWeblog #

The problem with the above is that there is no place for the pubdate or source, and there are two "extra" parameters which are unused.  These problems are corrected in the MetaWeblog API.  Dropping the two parameters, but otherwise sending the exact same post requires the following:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
    <params>

      <param>
        <value>0101679</value>
      </param>
      <param>
        <value>me</value>
      </param>
      <param>
        <value>gObBlEdYgOoK</value>
      </param>

      <param>
        <value>
          <struct>
            <member>
              <name>description</name>
              <value>..top secret report...</value>
            </member>
          </struct>
        </value>
      </param>

    </params>
</methodCall>

Additional parameters #

Sending the same information does not demonstrate the power of the MetaWeblog API, which is it's ability to carry additional data.  Here's the full version of the original request:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
    <params>

      <param>
        <value>0101679</value>
      </param>
      <param>
        <value>me</value>
      </param>
      <param>
        <value>gObBlEdYgOoK</value>
      </param>

      <param>
        <value>
          <struct>
            <member>
              <name>description</name>
              <value>..top secret report...</value>
            </member>
            <member>
              <name>pubDate</name>
              <value>Sat, 01 Jun 2002 04:55:43 GMT</value>
            </member>
            <member>
              <name>source</name>
              <value>
                <struct>
                  <member>
                    <name>url</name>
                    <value>http://partners.userland.com/nyt/nytHomepage.xml</value>
                  </member>
                  <member>
                    <name>name</name>
                    <value>New York Times: NYT HomePage</value>
                  </member>
                </struct>
              </value>
            </member>
          </struct>
        </value>
      </param>
    </params>
</methodCall>

Change in the API #

RSS 2.0 is extensible, so instead of enumerating the mapping of every possible element, it is desirable to come up with a general rule which can apply to all. This lead to another RFC. Unfortunately, the rule is slightly different than the original mapping, so for complete interoperability applications should be coded to accept either.  Here is the updated datastream, and the difference is slight:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
    <params>

      <param>
        <value>0101679</value>
      </param>
      <param>
        <value>me</value>
      </param>
      <param>
        <value>gObBlEdYgOoK</value>
      </param>
      <param>
      <value>
        <struct>
          <member>
            <name>description</name>
            <value>..top secret report...</value>
          </member>
          <member>
            <name>pubDate</name>
            <value>Sat, 01 Jun 2002 04:55:43 GMT</value>
          </member>
          <member>
            <name>source</name>
            <value>
               <struct>
                 <member>
                   <name>url</name>
                   <value>http://partners.userland.com/nyt/nytHomepage.xml</value>
                 </member>
                 <member>
                   <name>_value</name>
                   <value>New York Times: NYT HomePage</value>
                 </member>
               </struct>
            </value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodCall>

Categories part I #

Now lets turn our attention on the second item.  Here's one mapping of an item with categories to XML RPC:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
  <params>

    <param>
      <value>0101679</value>
    </param>
    <param>
      <value>me</value>
    </param>
    <param>
      <value>gObBlEdYgOoK</value>
    </param>

    <param>
      <value>
        <struct>
          <member>
            <name>description</name>
            <value>Evolution of Weblog APIs</value>
          </member>
          <member>
            <name>link</name>
            <value>http://www.intertwingly.net/stories/2003/01/26/evolve.html</value>
          </member>
          <member>
            <name>category</name>
            <value>RSS</value>
          </member>
          <member>
            <name>category</name>
            <value>XMLRPC</value>
          </member>

        </struct>
      </value>
    </param>
  </params>
</methodCall>

Alternate Encoding #

Since category has an optional attribute which happens to be omitted, there's another representation of this same data.  Presumably, applications need to be prepared to accept both:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
  <params>

    <param>
      <value>0101679</value>
    </param>
    <param>
      <value>me</value>
    </param>
    <param>
      <value>gObBlEdYgOoK</value>
    </param>

    <param>
      <value>
        <struct>
          <member>
            <name>description</name>
            <value>Evolution of Weblog APIs</value>
          </member>
          <member>
            <name>link</name>
            <value>http://www.intertwingly.net/stories/2003/01/26/evolve.html</value>
          </member>
          <member>
            <name>category</name>
            <value>
               <struct>
                 <member>
                   <name>_value</name>
                   <value>RSS</value>
                 </member>
               </struct>
            </value>
          </member>
          <member>
            <name>category</name>
            <value>
               <struct>
                 <member>
                   <name>_value</name>
                   <value>XMLRPC</value>
                 </member>
               </struct>
            </value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodCall>

Duplicate Names #

The above are valid XML RPC.  Unfortunately, they won't work with most common XML RPC toolkits, such as Frontier and Radio Userland.  This is due to two elements in the same structure having the same name.  In order to support this scenario, another encoding has been settled on for Radio, specifically for the category paramter, and with a limitation on domains. The resulting data stream would look like this:

<methodCall>
  <methodName>metaWeblog.newPost</methodName>
  <params>

    <param>
      <value>0101679</value>
    </param>
    <param>
      <value>me</value>
    </param>
    <param>
      <value>gObBlEdYgOoK</value>
    </param>

    <param>
      <value>
        <struct>
          <member>
            <name>description</name>
            <value>Evolution of Weblog APIs</value>
          </member>
          <member>
            <name>link</name>
            <value>http://www.intertwingly.net/stories/2003/01/26/evolve.html</value>
          </member>
          <member>
            <name>category</name>
            <value>
               <array>
                 <data>
                   <value>RSS</value>
                   <value>XMLRPC</value>
                 </data>
               </array>
            </value>
          </member>
        </struct>
      </value>
    </param>
  </params>
</methodCall>

RESTful alternative #

REST is an alternative to RPC which focuses on uniform interfaces and representations of data.  As RSS 2.0 already specifies a representation of the data, there isn't much more required.  The uniform interface for sending such data is POST.  How such a request is to be interpreted depends on where you send it.  If you send it to the URL of an existing weblog, it is a new post.  Post this same data to a validator, and it is validated.  Post this same data to another place and it is archived.  Post it to an existing weblog entry, and it is a comment.  The possibilities are unlimited.  

Here's the second example with full HTTP headers included this time:

POST /news/0101679 HTTP/1.1
Authorization: Basic gObBlEdYgOoK

<item>
  <description>Evolution of Weblog APIs</description>
  <link>http://www.intertwingly.net/stories/2003/01/26/evolve.html</link>
  <category>RSS</category>
  <category>XML-RPC</category>
</item>

SOAP #

SOAP is a protocol which supports both RPC encoded and document literal styles of interaction.  While REST focuses on transfer level concepts such as authentication and authorization, SOAP can build upon these and add concepts such as application level authentication and authorization.  What does this mean?  In some cases instead of sending the data using HTTP, one can send the data using a reliable messaging service such as JMS or even a simple store and forward mechanism such as e-mail.  Since the authentication and authorization information is in the data, it arrives intact.  This is done quite simply by putting the data in an envelope which has room for headers.  Here is a hypothetical mapping of this request to SOAP:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">

  <soap:Header>
    <blogger xmlns="http://plant.blogger.com/api/index.html">
      <blogid>0101679</blogid>
      <username>me</username>
      <password>gObBlEdYgOoK</password>
    </blogger>
  </soap:Header>

  <soap:Body>
    <item>
      <description>Evolution of Weblog APIs</description>
      <link>http://www.intertwingly.net/stories/2003/01/26/evolve.html</link>
      <category>RSS</category>
      <category>XML-RPC</category>
    </item>
  </soap:Body>

</soap:Envelope>

Conclusion #

If you are in the fortunate position where you essentially control both ends of the wire, and the parameters being passed are a simple series of strings and integers, use whatever seems easiest to you.  This includes XML RPC, RMI, DCOM, or simply putting query arguments on the URL itself.

If these conditions do not apply, focus on creating an extensible definition of the data itself, and then on uniform interfaces for transferring this information around.

Search

Valid XHTML 1.1!