3

When using xmlrpclib in python an error on the server side is reported by the client side as an xmlrpclib.Fault. A division by zero error in a method on the server side (using SimpleXMLRPCServer) usually gives an output like the following:

xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero">

This is useful as it notes the type of error, but now where it happened. How is it possible to overwrite/modify the xmlrpclib.Fault method (in SimpleXMLRPCServer?) so it reports the error e.g. as follows:

xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero MODULE: myMethod.py  LINE: 657">

i.e. to include the name of the module the error appeared and the line number. Is that possible to do on the server-side, without raising custom exceptions? ANY error should reported in the same way on the client side.

2
  • This is a server-side issue; what did you use to implement the server? Commented Jan 21, 2013 at 16:27
  • Well, just the standard SimpleXMLRPCServer. And on this side I would like to overwrite/change/extend the Fault behavior. Commented Jan 21, 2013 at 16:31

1 Answer 1

4

If you use SimpleXMLRPCServer, you can override the internal _marshaled_dispatch method to add information to the Fault() instance generated:

This is the original method:

def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
    try:
        params, method = xmlrpclib.loads(data)

        # generate response
        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,
                                   allow_none=self.allow_none, encoding=self.encoding)
    except:
        # report low level exception back to server
        # (each dispatcher should have handled their own
        # exceptions)
        exc_type, exc_value = sys.exc_info()[:2]
        response = xmlrpclib.dumps(
            xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
            encoding=self.encoding, allow_none=self.allow_none)
    return response

You can subclass SimpleXMLRPCServer.SimpleXMLRPCServer and override this method:

import SimpleXMLRPCServer
import sys
import xmlrbclib

class VerboseFaultXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
    def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
        try:
            params, method = xmlrpclib.loads(data)

            # generate response
            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,
                                       allow_none=self.allow_none, encoding=self.encoding)
        except:
            # report low level exception back to server
            # (each dispatcher should have handled their own
            # exceptions)
            exc_type, exc_value, tb = sys.exc_info()
            while tb.tb_next is not None:
                tb = tb.tb_next  # find last frame of the traceback
            lineno = tb.tb_lineno
            code = tb.tb_frame.f_code
            filename = code.co_filename
            name = code.co_name
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s FILENAME: %s LINE: %s NAME: %s" % (
                    exc_type, exc_value, filename, lineno, name)),
                encoding=self.encoding, allow_none=self.allow_none)
        return response

Then use VerboseFaultXMLRPCServer instead of SimpleXMLRPCServer.SimpleXMLRPCServer.

Sign up to request clarification or add additional context in comments.

2 Comments

The actual method _marshaled_dispatch looks different in my case, I guess because I am using python 2.7. Nevertheless, the principle is clear so, as a first test, I created a subclass with the original _marshaled_dispatch method. However, this gives me a 500 Internal Server Error on the client side. When I use SimpleXMLRPCServer.SimpleXMLRPCServer again, the Fault is being reported again as before. I really do not understand why I get this server error now...
@Alex: No, that was my fault; I looked at the wrong section. Corrected now, and tested too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.