[mod_python] how to handle xforms with publisher handler

Jim Gallacher jpg at jgassociates.ca
Thu Jan 11 22:04:11 EST 2007


Graham Dumpleton wrote:
> Jim Gallacher wrote ..
>> Emiliano Moscato wrote:
>>> Hi all!
>>>
>>> I'm getting crazy trying to receive xforms xml data with mod_python +
>>> publisher handler.
> 
> In what way are you using mod_python.publisher? Depending to what
> degree you are using it, mod_python 3.3 offers some alternate mechanisms
> for doing basic dispatch against different resources which might be more
> useful and allow you to still access content of response to decode it.
> 
>>> In a normal HTML form, the data would be sent as
>>> application/x-www-form-urlencoded, in the XForms world however, this
>>> information is sent as XML formatted data (application/xml).
>>> Up to now I've used cherryPy as web server and I've got my xml data with
>>> cherrypy.threadData.xform.
>>> I've read that PHP receive this in $HTTP_RAW_POST_DATA variable. If I
>> send
>>> the form to a php script all work fine.
>>> But when I try to submit a xforms with method POST to a script managed
>> by
>>> publisher handler I get an error with no log in my apache server error
>> log.
>>> Any help?
>> You'll need to elaborate on the error you are getting, but I think part
>> of the problem is that you are bumping up against part of the internal
>> "magic" of publisher.
>>
>> Publisher automatically creates a FieldStorage instance. Unfortunately
>> FieldStorage assumes that the content-type starts with either 
>> "application/x-www-form-urlencoded" or "multipart/". If I had to guess
>> I'd say that you are getting "501 Not Implemented error" as a result.
>>
>> Here are a couple of solutions that you might consider as a workaround:
>>
>> 1. Hack util.FieldStorage to properly handle your content-type. If you
>> do this feel free to submit a patch so FieldStorage can be fixed. ;)
> 
> Hmmm, xforms is quite different.
> 
>   http://www.w3.org/TR/xforms/
> 
> Looks like a lot of work.

Probably. I certainly wasn't offering to do it. ;)

>> 2. Hack publisher to skip the automatic creation of FieldStorage. (Line
>> 424 in publisher.py for mod_python 3.3.0b). You can then use req.read()
>> to read and process the POST'd data within your content handler.
> 
> I've raised this issue before about publisher not being able to accept other
> content types. See:
> 
>   http://issues.apache.org/jira/browse/MODPYTHON-29
> 
> Also, like PSP now does, publisher could be made to use 'req.form' if it
> already existed. This would allow a stacked response handler before
> publisher to decide whether some other form content was supplied, decode
> it and set req.form to a compatible class to FieldStorage. I don't know that I
> have created an issue for that idea before, but have certainly thought
> about it and perhaps mentioned it on the mailing list.

That seems like a reasonable solution.

>> 3. Use a PythonFixupHandler before the content handler. In the 
>> fixuphandler use req.read() to grab the raw data and adjust the 
>> content-type header so that FieldStorage doesn't bomb out. Note that if
>> you want to pass xml field data as parameters to your handler method 
>> you'll need to do a bit more work. For example
>>
>> def index(foo="bar"):
>>      return "whatever"
>>
>> won't get foo from your xml data. You can likely work around this but 
>> you'll need to take a look at the source for FieldStorage and publisher
>> to work out a strategy.
> 
> If you are talking about modifying the input stream, an input filter would
> perhaps be better. Not sure that that will help since xforms is quite
> different and isn't just a matter of changing content type.

No, I was just thinking you could get the raw data with req.read() 
(parsing the xml or whatever) and then set the content-type to 
application/x-www-form-urlencoded. That way the subsequent call to 
FieldStorage within publisher won't bomb out. The code would look 
something like this:

def fixuphandler(req):
     if req.headers_in.has_key("content-type"):
         ctype = req.headers_in["content-type"]
         if ctype.startswith("application/xml"):
             req.data = parse_the_xml_data_or_whatever(req.read())
             req.headers_in["content-type"] =
                      "application/x-www-form-urlencoded"
     return apache.OK

A little too hackish perhaps? (Assuming it would even work).

Jim


More information about the Mod_python mailing list