Python
  Home arrow Python arrow Page 2 - The Python Web Services Developer: Par...
Dev Shed Forums 
Administration  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Forums Sitemap 
IBM® developerWorks 
Dedicated Servers 
E-Commerce Hosting 
Linux Web Hosting 
Managed Hosting 
Small Business Hosting 
Download TestComplete 
VPS Hosting 
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
PYTHON

The Python Web Services Developer: Part 3
By: Mike Olson and Uche Ogbuji
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating:  stars stars stars stars stars / 0
    2003-07-31

    Table of Contents:
  • The Python Web Services Developer: Part 3
  • Article
  • Moving Right Along

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
     
    ADVERTISEMENT

    Stay one step ahead of the competition. Evaluate and give feedback on some of the hottest web development tools on the market today. Make your opinion heard! Click Here

    The Python Web Services Developer: Part 3 - Article
    (Page 2 of 3 )

    Software by Post

    To begin with we should look at updates using simple HTTP POST. This can serve as a means for both human contributors and software agents to provide updates, the former by way of a browser form.

    Start by making sure that the software repository core is set up using the steps we explained in part 2. Unfortunately, there's a twist. The last article was based on 4Suite Server version 0.10.2, but since then we released version 0.11.0, with significant improvements. See Resources for an update to the last article that covers the 0.11.0 release.

    Let's say the form for contributors to use in adding entries to the repository is as in Figure 1. This corresponds to the HTML in Listing 1.

    Figure 1: Form for Adding New Software to the Repository

    4Suite Server allows us to set up an XSL transform to handle POST requests such as this form generates, creating a new document that is added to the XML repository. The XSL transform we use for the purpose of adding an entry to the software repository is in Listing 2.

    Theaction attribute of the form element in our HTML source is interpreted with the document at the path in the URI as the source, and thetemplate-xslt argument is interpreted as the XSL transform to use for generating the new document.

    Listing 2: XSLT transform to turn HTTP POST data into a new XML document

    <?xml version="1.0"?>
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:ftext="http://xmlns.4suite.org/ext"
      extension-element-prefixes="ftext"
      version="1.0"
    >
      <xsl:param name='title'/>
      <xsl:param name='creator'/>
      <xsl:param name='home'/>
      <xsl:param name='version'/>
      <xsl:param name='description'/>
      <xsl:template match="/">
    <rdf:RDF
      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
      xmlns:dc="http://purl.org/dc/elements/1.1"
      xmlns="http://namespaces.4suite.org/www/software-map"
    >
      <Software rdf:ID="{$title}">
        <dc:Title><xsl:value-of select='$title'/></dc:Title>
        <dc:Creator><xsl:value-of select='$creator'/></dc:Creator>
        <dc:Description><xsl:value-of select='$description'/></dc:Description>
        <CurrentVersion><xsl:value-of select='$version'/></CurrentVersion>
        <Home rdf:resource="{$home}"/>
      </Software>
    </rdf:RDF>
        <ftext:set-post-template-params
          new-doc-uri="incoming/{$title}-{$version}.xml"
          response-uri="thanks.xhtml"
          docdef="dublin_core"
        />
      </xsl:template>
    </xsl:stylesheet>

    The first thing to note is the group of parameters such astitle andcreator. These are automatically set by the server to the values from the form elements of the same name, which become HTTP POST query arguments. These parameters can then be used to craft the output using all the tools XSLT places at our disposal. As you can see, the transform is creating a software description document in the form we introduced in the first part of this series. We omitted some optional fields for simplicity.

    Finally, observe theftext:set-post-template-params extension element at the end of the transform. This is a special extension set up by the server which allows you to set such important parameters as the URI of the document to be added, its document definition and the URI to be used by the server to generate the HTML to be sent in response to the HTTP POST (this is, for instance, the HTML that would appear in the browser after the "Submit" button was clicked to submit an entry).

    The steps involved are briefly outlined here:

    1. Create a container and give universal read access to it.
    2. Create a document for the HTTP POST operation.
    3. Create the XSLT template.
    4. Create the submission response document.
    5. Create the container to store the output.

    To try this yourself, first create an appropriate container and grand universal read access to it:

    Listing 3a

    $ 4ss create container /softrepo
    $ 4ss set acl --world-read /softrepo

    Then create a simple dummy document (just "<null/>") as the HTTP POST target. For example:

    Listing 3b

    $ 4ss create document - BASE_XML /softrepo/submit-new-software-entry
    <null/>
    $ 4ss set acl --world-read /softrepo/submit-new-software-entry

    If you specify "-" as the source for the XML document, the command will read the XML source from standard input. Next, create the template XSLT document, as shown below:

    Listing 3c

    $ 4ss create document submit-entry.xslt BASE_XSLT /softrepo/submit-entry.xslt
    $ 4ss set acl --world-read softrepo/submit-entry.xslt

    Now create the submission response document as follows:

    Listing 3d

    $ 4ss create document - BASE_XML softrepo/thanks.xhtml
    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
    <html xmlns='http://www.w3.org/1999/xhtml'>
    <head>
    <title>Thanks for your submission</title>
    </head>
    <body>
      <p>Thanks for your submission to the software repository.</p>
    </body>
    $ 4ss set acl --world-read softrepo/thanks.xhtml

    Finally, create the container where submitted software records will go. This one must be world-writable in order for the documents to be added by anonymous users. See listing 3e.

    Listing 3e

    $ 4ss create container softrepo/incoming
    $ 4ss set acl --world-write softrepo/incoming

    Once this is set up, people can enter the data into a form, or software agents can enter the data using HTTP libraries in the language of choice. There is, however, an alternative growing in popularity for software-to-software access of data, without involving humans.

    Software on a Rope
    4Suite Server implements the basic SOAP API, which we can use as the basis of our software repository Web service.

    Listing 4 is a simple Python command-line program that adds a software entry file using the direct SOAP API. Note the special encoding stylehttp://4suite.org/4ss/direct used in the direct 4Suite Server API. This encoding basically consists of an element representing the method invocation and attributes representing the parameters, and in some cases a body containing a document that serves as a parameter. Other than that, Listing 4 is pretty straightforward code to construct an XML representing a SOAP request document from command-line parameters -- put this into an HTTP request, send it off and listen for the response.

    Listing 4: A Python Program to Send a SOAP Request According to the Core API

    import sys, string, httplib, base64, mimetools
    SERVER_ADDR = '127.0.0.1'
    SERVER_PORT = 8080
    BODY_TEMPLATE = """<SOAP-ENV:Envelope
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:ft="http://xmlns.4suite.org/services"
      SOAP-ENV:encodingStyle="http://4suite.org/4ss/direct"
    >
      <SOAP-ENV:Body>
        <ft:Create doc-def-name="%s" uri="%s">
    %s
        </ft:Create>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>"""
    #define the function
    def AddSoftwareFromFile(entry, docdef, uri):
        body = BODY_TEMPLATE%(docdef, uri, base64.encodestring(entry))
        blen = len(body)
        requestor = httplib.HTTP(SERVER_ADDR, SERVER_PORT)
        requestor.putrequest('POST', '/soap-handler')
        requestor.putheader('Host', SERVER_ADDR)
        requestor.putheader('Content-Type', 'text/plain; charset="iso-8859-1"')
        requestor.putheader('Content-Length', str(blen))
        requestor.putheader('SOAPAction', "")
        requestor.endheaders()
        requestor.send(body)
        (status_code, message, reply_headers) = requestor.getreply()
        reply_body = requestor.getfile().read()
        print status_code
        print message
        print reply_body
    if __name__ == "__main__":
        fname = sys.argv[1]
        docdef = sys.argv[2]
        uri = sys.argv[3]
        entry = open(fname, 'r').read()
        AddSoftwareFromFile(entry, docdef, uri)

    A sample session running this program is shown in Listing 4b.

    As you can see, the server merely echoes back the document added to the repository.

    But what if we simply want to pass the server a few bits of relevant information for us and have it construct the software repository entry, as we did in the above HTTP POST example? 4Suite Server allows you to write your own specialized SOAP handler as shown in the example in Listing 5. This example handles SOAP messages consisting of the various fields describing the software, composes the description file on the server side, and then, adds it to the repository.

    The most important part of this module is theSoftRepoSoapHandler class that is subclassed from the 4Suite Server SoapHandler. All the customized class has to do is define a mapping,NS_TO_HANDLER_MAPPING, which for each namespace defines another mapping from SOAP body element name to a handler function. In our case, we set up theAddEntry function to handle our intended requests.

    In order to use this handler module, we must register it with 4Suite Server. This can be done by copying the Python file to a spot on the PYTHONPATH and appending a stanza such as the following to the configuration file.See listing 6a.

    Listing 6a

    <rdf:Description ID='SoftRepoSoapHandler'>
        <rdf:type resource='http://xmlns.4Suite.org/4ss/properties#HttpHandler'/>    
        <Priority>30</Priority>
        <Module>SoftRepoSoapHandler</Module>
      </rdf:Description>

    You also need to add a line to the PythonServer or ApacheServer configuration stanza referring to the new handler we set up:

    Listing 6b

      <Handler resource='#SoftRepoSoapHandler'/>

    Once the handler is set up, you can make even simpler SOAP calls to add an entry to the software repository. Listing 7 is example client code for the purpose.

    Listing 7: An example client to the software repository

    import sys, httplib
    SERVER_ADDR = '127.0.0.1'
    SERVER_PORT = 8080
    BODY_TEMPLATE = """<SOAP-ENV:Envelope
      xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
      xmlns:s="http://spam.com/softrepo"
      SOAP-ENV:encodingStyle="http://spam.com/softrepo/encoding"
    >
      <SOAP-ENV:Body>
        <s:Add>
          <s:Title><![CDATA[%s</s:Title>
          <s:Creator><![CDATA[%s</s:Creator>
          <s:Home><![CDATA[%s</s:Home>
          <s:Version><![CDATA[%s</s:Version>
          <s:Description><![CDATA[%s</s:Description>
        </s:Add>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>"""
    #define the function
    def AddEntry(title, version):
        creator = raw_input("Creator: ")
        home = raw_input("Home: ")
        desc = raw_input("Description: ")
        body = BODY_TEMPLATE%(title, creator, home, version, desc)
        blen = len(body)
        requestor = httplib.HTTP(SERVER_ADDR, SERVER_PORT)
        requestor.putrequest('POST', '/softrepo/soap-handler')
        requestor.putheader('Host', SERVER_ADDR)
        requestor.putheader('Content-Type', 'text/plain; charset="iso-8859-1"')
        requestor.putheader('Content-Length', str(blen))
        requestor.putheader('SOAPAction', "")
        requestor.endheaders()
        requestor.send(body)
        (status_code, message, reply_headers) = requestor.getreply()
        reply_body = requestor.getfile().read()
        print status_code
        print message
        print reply_body
    if __name__ == "__main__":
        title = sys.argv[1]
        version = sys.argv[2]
        AddEntry(title, version)

    Save Listing 7 asadd_software2.py and try it out as shown in Listing 7b.

    More Python Articles
    More By Mike Olson and Uche Ogbuji


     

       

    PYTHON ARTICLES

    - SSH with Twisted
    - Mobile Programming in Python using PyS60: UI...
    - Python: Count on It
    - Python Strings: Spinning Yarns
    - Python: More Fun with Strings
    - Python: Stringing You Along
    - Python Operators
    - Bluetooth Programming in Python: Network Pro...
    - Python Sets
    - Python Conditionals, Lists, Dictionaries, an...
    - Python: Input and Variables
    - Introduction to Python Programming
    - Mobile Programming in Python using PyS60: Ge...
    - Bluetooth Programming using Python
    - Finishing the PyMailGUI Client: User Help To...

     
    Accelerating Trading Partner Performance
     
    Competing on Analytics
     
    Cost Effective Scaling with Virtualization and Coyote Point Systems
     
    Five Checkpoints to Implementing IP Telephony
     
    Hosted Email Security: Staying Ahead of New Threats
     




    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 5 hosted by Hostway