If someone here has spare Brain/CPU cycles, could you look at the attached
code and provide feedback?
Grisha
---------- Forwarded message ----------
Date: Mon, 30 Jan 2006 18:04:42 -0800
From: Matt Chisholm <[EMAIL PROTECTED]>
Subject: Re: contribution to mod_python: Apache + SimpleXMLRPCServer
On Jan 30 2006, 11:42, Matt Chisholm wrote:
We've written a few classes to use the SimpleXMLRPCServer module in
Python with mod_python instead of the Python CGI module. We've been
using it internally for a while and we'd like to contribute it back to
the mod_python project; we don't really have the time to create a
separate project for it, but it seems like something that would be
useful to many people.
We agree to assign copyright of this code to the mod_python project
and to license it under the mod_python license. Our employer,
BitTorrent Inc., also agrees.
I've attached a copy of the code.
Please let me know if this is not the right channel to send
contributions; also, I'm not on this list so please respond to me
individually.
Matt Chisholm
# Written by Matt Chisholm and Greg Hazel
# This should probably be contributed back to the mod_python project
from mod_python import apache
from SimpleXMLRPCServer import CGIXMLRPCRequestHandler
from DocXMLRPCServer import DocCGIXMLRPCRequestHandler
import traceback
import xmlrpclib
from xmlrpclib import Fault
import sys
class stderr_mod_python(object):
def __init__(self, request):
self.request = request
def write(self, s):
l = s.strip('\r\n')
for e in l.split('\n'):
s = "%s %s: %s" % (self.request.phase, self.request.hlist.handler, e)
# this logs in the mod_python fashion to the error log for this request's virtual server
self.request.log_error(s, apache.APLOG_NOERRNO|apache.APLOG_ERR)
class ApacheXMLRPCRequestHandler(CGIXMLRPCRequestHandler):
def _write(self, request, response, content_type='text/xml'):
request.send_http_header()
request.content_type = content_type
request.write(response)
# SimpleXMLRPCServer doesn't do what we want
def _marshaled_dispatch(self, data, dispatch_method = None):
"""Dispatches an XML-RPC method from marshalled (XML) data.
XML-RPC methods are dispatched from the marshalled (XML) data
using the _dispatch method and the result is returned as
marshalled data. For backwards compatibility, a dispatch
function can be provided as an argument (see comment in
SimpleXMLRPCRequestHandler.do_POST) but overriding the
existing method through subclassing is the prefered means
of changing method dispatch behavior.
"""
params, method = xmlrpclib.loads(data)
# men have been killed for less
temp = sys.stderr
sys.stderr = stderr_mod_python(self.request)
# generate response
try:
if dispatch_method is not None:
response = dispatch_method(method, params)
else:
response = self._dispatch(method, params)
# wrap response in a singleton tuple
response = (response,)
response = xmlrpclib.dumps(response, methodresponse=1)
except Fault, fault:
response = xmlrpclib.dumps(fault)
except Exception, e:
# report exception back to server
response = xmlrpclib.dumps(
xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
)
# and also log it, duh
etype, evalue, etb = sys.exc_info()
stack = traceback.format_exception(etype, evalue, etb)
for l in stack:
sys.stderr.write(l)
sys.stderr = temp
return response
def handle_xmlrpc(self, request):
xml_request = request.read()
self.request = request
response = self._marshaled_dispatch(xml_request)
self._write(request, response)
return apache.OK
def handle_get(self, request):
return apache.HTTP_BAD_REQUEST
def handle_request(self, request):
if request.method == 'POST':
responsecode = self.handle_xmlrpc(request)
elif request.method == 'GET':
responsecode = self.handle_get(request)
else:
responsecode = apache.HTTP_BAD_REQUEST
return responsecode
class DocApacheXMLRPCRequestHandler(ApacheXMLRPCRequestHandler, DocCGIXMLRPCRequestHandler):
def __init__(self):
# calling __init__ manually is necessary here
ApacheXMLRPCRequestHandler.__init__(self)
DocCGIXMLRPCRequestHandler.__init__(self)
def handle_get(self, request):
response = self.generate_html_documentation()
self._write(request, response, content_type='text/html')
return apache.OK