Commits

Olemis Lang committed a0e7e18

XML-RPC protocol refactored and tested ?

Comments (0)

Files changed (1)

t5437\t5437-protocol_api_v2-r7194.diff

 
 diff -r a475cf08e780 trunk/tracrpc/api.py
 --- a/trunk/tracrpc/api.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/api.py	Sat Mar 13 23:45:54 2010 -0500
++++ b/trunk/tracrpc/api.py	Sun Mar 14 02:09:01 2010 -0500
 @@ -21,13 +21,34 @@
      """ RPC Binary type. Currently == xmlrpclib.Binary. """
      pass
  
  RPC_TYPES = {int: 'int', bool: 'boolean', str: 'string', float: 'double',
               datetime: 'dateTime.iso8601', Binary: 'base64',
-@@ -63,8 +84,56 @@
+@@ -63,8 +84,57 @@
                     (/login)?/<path_item>. Answer to 'rpc' only if possible.
          content_type: Starts-with check of 'Content-Type' request header. """
  
 +        """Send a fault message back to the caller. Exception type 
 +        and message are used for this purpose. This message *SHOULD* 
 +        handle `RPCError`, `PermissionError`, and `ResourceNotFound` 
-+        and subclasses.
++        and subclasses. This method is called from within an exception 
++        handler.
 +        
 +        rpcreq  : The same object returned by `parse_rpc_request` 
 +                  (see above).
  
 diff -r a475cf08e780 trunk/tracrpc/json_rpc.py
 --- a/trunk/tracrpc/json_rpc.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/json_rpc.py	Sat Mar 13 23:45:54 2010 -0500
++++ b/trunk/tracrpc/json_rpc.py	Sun Mar 14 02:09:01 2010 -0500
 @@ -5,8 +5,9 @@
  (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
  """
      def _json_error(self, e, c=None, r_id=None):
 diff -r a475cf08e780 trunk/tracrpc/web_ui.py
 --- a/trunk/tracrpc/web_ui.py	Sat Mar 13 19:59:29 2010 -0500
-+++ b/trunk/tracrpc/web_ui.py	Sat Mar 13 23:45:54 2010 -0500
++++ b/trunk/tracrpc/web_ui.py	Sun Mar 14 02:09:01 2010 -0500
 @@ -6,6 +6,10 @@
  (c) 2009      ::: www.CodeResort.com - BV Network AS (simon-code@bvnetwork.no)
  """
      # ITemplateProvider methods
  
      def get_htdocs_dirs(self):
+diff -r a475cf08e780 trunk/tracrpc/xml_rpc.py
+--- a/trunk/tracrpc/xml_rpc.py	Sat Mar 13 19:59:29 2010 -0500
++++ b/trunk/tracrpc/xml_rpc.py	Sun Mar 14 02:09:01 2010 -0500
+@@ -19,7 +19,7 @@
+ from trac.util.text import to_unicode
+ 
+ from tracrpc.api import XMLRPCSystem, IRPCProtocol, Binary, \
+-        RPCError, MethodNotFound
++        RPCError, MethodNotFound, ProtocolException, ServiceException
+ from tracrpc.util import empty, prepare_docs
+ 
+ __all__ = ['XmlRpcProtocol']
+@@ -81,41 +81,46 @@
+         yield ('xmlrpc', 'application/xml')
+         yield ('xmlrpc', 'text/xml')
+ 
+-    def rpc_process(self, req, content_type):
+-        """ Handles XML-RPC requests """
++    def parse_rpc_request(self, req, content_type):
++        """ Parse XML-RPC requests."""
+         try:
+             args, method = xmlrpclib.loads(
+                         req.read(int(req.get_header('Content-Length'))))
+         except Exception, e:
+             self.log.debug("RPC(xml) parse error: %s", to_unicode(e))
+-            self._send_response(req,
+-                    xmlrpclib.dumps(
+-                        xmlrpclib.Fault(-32700, to_unicode(e))), content_type)
+-            return
+-        self.log.debug("RPC(xml) call by '%s', method '%s' with args: %s" \
+-                                    % (req.authname, method, repr(args)))
+-        args = self._normalize_xml_input(args)
+-        try:
+-            req.perm.require('XML_RPC') # Need at least XML_RPC
+-            result = XMLRPCSystem(self.env).get_method(method)(req, args)
+-            self.env.log.debug("RPC(xml) '%s' result: %s" % (
+-                                                        method, repr(result)))
+-            result = tuple(self._normalize_xml_output(result))
+-            self._send_response(req,
+-                    xmlrpclib.dumps(result, methodresponse=True), content_type)
+-        except MethodNotFound, e:
+-            self._send_response(req,
+-                    xmlrpclib.dumps(
+-                        xmlrpclib.Fault(-32601, to_unicode(e))), content_type)
+-        except PermissionError, e:
+-            self._send_response(req,
+-                    xmlrpclib.dumps(
+-                        xmlrpclib.Fault(403, to_unicode(e))), content_type)
+-        except ResourceNotFound, e:
+-            self._send_response(req,
+-                    xmlrpclib.dumps(
+-                        xmlrpclib.Fault(404, to_unicode(e))), content_type)
+-        except Exception, e:
++            raise ProtocolException(xmlrpclib.Fault(-32700, to_unicode(e)))
++        else :
++            self.log.debug("RPC(xml) call by '%s', method '%s' with args: %s" \
++                                        % (req.authname, method, repr(args)))
++            args = self._normalize_xml_input(args)
++            return {'method' : method, 'params' : args}
++
++    def send_rpc_result(self, req, rpcreq, result):
++        """Send the result of the XML-RPC call back to the client."""
++        method = rpcreq.get('method')
++        self.log.debug("RPC(xml) '%s' result: %s" % (
++                                                    method, repr(result)))
++        result = tuple(self._normalize_xml_output([result]))
++        self._send_response(req,
++                xmlrpclib.dumps(result, methodresponse=True), rpcreq['mimetype'])
++
++    def send_rpc_error(self, req, rpcreq, e):
++        """Send an XML-RPC fault message back to the caller"""
++        fault = None
++        if isinstance(e, ProtocolException):
++            fault = e._exc
++        elif isinstance(e, ServiceException):
++            e = e._exc
++        elif isinstance(e, MethodNotFound):
++            fault = xmlrpclib.Fault(-32601, to_unicode(e))
++        elif isinstance(e, PermissionError):
++            fault = xmlrpclib.Fault(403, to_unicode(e))
++        elif isinstance(e, ResourceNotFound):
++            fault = xmlrpclib.Fault(404, to_unicode(e))
++
++        if fault is not None :
++            self._send_response(req, xmlrpclib.dumps(fault), rpcreq['mimetype'])
++        else :
+             self.log.error(e)
+             import traceback
+             from tracrpc.util import StringIO