Skip to main content

If you don't have an IBM ID and password, register here.

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

Tip: Make your CGI scripts available via XML-RPC

Providing a programmatic interface to Web services

David Mertz (mertz@gnosis.cx), Interfacer, Gnosis Software, Inc.
David Mertz knows a little bit about a lot of things, but a lot about fewer things than he once did. The smooth overcomes the striated. David can be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/.

Summary:  For a large class of CGI scripts, it is both easy and useful to provide an alternate XML-RPC interface to the same calculation or lookup. If you do this, other developers can quickly utilize the information you provide within their own larger applications. This tip shows you how.

View more content in this series

Date:  30 Apr 2003
Level:  Introductory

Comments:  

Many CGI scripts are, at their heart, just a form of remote procedure call. A user specifies some information, perhaps in an HTML form, and your Web server returns a formatted page that contains an answer to their inquiry. The data on this return page is surrounded by some HTML markup, but basically it is the data that is of interest. Examples of data-oriented CGI interfaces are search engines, stock price checks, weather reports, personal information lookup, catalog inventory, and so on.

A Web browser is a fine interface for human eyes, but a returned HTML page is not an optimal format for integration within custom applications. What programmers often do to utilize the data that comes from CGI queries is screen-scraping of returned pages -- that is, they look for identifiable markup and contents, and pull data elements from the text. But screen-scraping is error-prone; page layout might change over time or might be dependent on the specific results. A more formal API is better for programmatic access to your CGI functionality.

XML-RPC is specifically designed to enable application access to queryable results over an HTTP channel. Its sibling, SOAP, can do a similar job, but the XML format of the SOAP is more complicated than is needed for most purposes. An ideal system is one where people can make queries in a Web browser, while custom applications can make the same queries using XML-RPC. The underlying server can do almost exactly the same thing in either case.

An example

I have created a service within my Web site that enables users to send e-mail to anonymized recipients. Rather than a traceable address, recipients can create a local anonym where they can get mail. You can read about the goals and architecture of Gnosis-Anon at its home page (see Resources). At the same URL, you can enter a query into an HTML form, and in return be presented with an HTML page informing you of an anonym. From there, you need to either write down the information or cut-and-paste the information into a tool other than your Web browser.

Suppose you want to utilize the anonym automatically in an application such as a Mail User Agent (MUA) or Mail Transport Agent (MTA). You might do some screen-scraping like the following:


Listing 1. get-anonym-cgi.py
                
                #!/usr/bin/env python
                
from urllib import urlencode, urlopen
from sys import argv base_url = 'http://gnosis.cx/cgi-bin/encode_address.cgi' query = urlencode({'duration':argv[1], 'email':argv[2]}) html_answer = urlopen(base_url+'?'+query).readlines() result = "NO ANONYM FOUND!"
for line in html_answer: if line.find("<dt>Anonym:</dt>") >= 0: start = line.find('<dd>')+4 end = line.find('</dd>') result = line[start:end] break
print result

You can run this with a command line like the following:


Listing 2. Running get-anonym-cgi
                % get-anonym-cgi.py perm mertz@gnosis.cx
.rNCOolqsVQYu@gnosis.cx

This works if I do not change the format of the HTML -- but that's a big if. A more robust (and simpler) client application might look like this:


Listing 3. get-anonym-xmlrpc.py
                
                #!/usr/bin/env python
                
import sys, xmlrpclib server = xmlrpclib.Server("http://gnosis.cx:8000") print server.anonym(sys.argv[1], sys.argv[2])

This XML-RPC application behaves exactly the same as the CGI-based one -- except that it will not break if the layout of the Web page changes slightly.


Setting up the XML-RPC server

Writing an XML-RPC server is not much different from writing a CGI script. The actual calculation or lookup code is identical; you only need to change the format of the output and do a little extra work parsing the inputs for CGI. My CGI script looks something like this:


Listing 4. encode_address.py
                
                #!/usr/bin/env python
                
import cgi query = cgi.FieldStorage() email = query.getvalue('email','test@test.lan') duration = query.getvalue('duration', 'Unknown') anonym = FIND_THE_ANONYM(duration, email) html_template = open('template').read() html = html_template % (email, anonym, duration) print "Content-Type: text/html"
print
print html

This leaves out the details of how FIND_THE_ANONYM() works and what the HTML template looks like, but those details are unimportant here. An XML-RPC server is even easier to program:


Listing 5. anonym-xmlrpc-server.py
                
                #!/usr/bin/env python
                
from SimpleXMLRPCServer import SimpleXMLRPCServer class Anonym: def anonym(self, duration, email): return FIND_THE_ANONYM(duration, email) def container_test(self): return {'spam':'eggs', 'bacon':'toast'} server = SimpleXMLRPCServer(('', 8000)) server.register_instance(Anonym()) server.serve_forever()

As you can see, the same lookup function is used; its return value is what is returned to a remote call to the .anonym() method. On the wire, return values are encoded as XML-RPC, but Python's xmlrpclib module automatically translates XML-RPC encoded structures back into native data structures, as do analogous libraries in other languages. The method .container_test() in Listing 5 can be called remotely as well, in which case the client will see a Python dictionary.


A few notes

These code examples use Python, but implementations of both XML-RPC clients and servers exist for a large number of programming languages. Moreover, XML-RPC itself is completely language-neutral; multiple clients written in different languages can call the same server, and none of them will care what language the server was written in.

There is a difference in the way a CGI script runs and the way this XML-RPC server runs. The XML-RPC server is its own process (and uses its own port). CGI scripts, on the other hand, are automatically generated by a general HTTP server. But both still travel over HTTP (or HTTPS) layers, so any issues with firewalls, statefulness, and the like remain identical. Moreover, some general-purpose HTTP servers support XML-RPC internally. But if, like me, you do not control the configuration of your Web host, it is easier to write a stand-alone XML-RPC server like the eight-line version in Listing 5.


Resources

About the author

David Mertz knows a little bit about a lot of things, but a lot about fewer things than he once did. The smooth overcomes the striated. David can be reached at mertz@gnosis.cx; his life pored over at http://gnosis.cx/dW/.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in

If you don't have an IBM ID and password, register here.


Forgot your IBM ID?


Forgot your password?
Change your password


By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)


By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML
ArticleID=12261
ArticleTitle=Tip: Make your CGI scripts available via XML-RPC
publish-date=04302003
author1-email=mertz@gnosis.cx
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).