Commits

Olemis Lang committed 3cfdb51

BH RPC : Improved error handling in XML-RPC and JSON-RPC to output std error codes. Raise InvalidWikiPage in WikiRPC handler methods

Comments (0)

Files changed (4)

trunk/tracrpc/json_rpc.py

 from trac.core import *
 from trac.perm import PermissionError
 from trac.resource import ResourceNotFound
+from trac.ticket.query import QuerySyntaxError, QueryValueError
 from trac.util.datefmt import utc
 from trac.util.text import to_unicode
 from trac.web.api import RequestDone
+from trac.wiki.web_ui import InvalidWikiPage
 
 from tracrpc.api import IRPCProtocol, XMLRPCSystem, Binary, \
-        RPCError, MethodNotFound, ProtocolException
+        RPCError, MethodNotFound, ProtocolException, ServiceException
 from tracrpc.util import exception_to_unicode, empty, prepare_docs
 
 __all__ = ['JsonRpcProtocol']
 
         def _json_error(self, e, c=None, r_id=None):
             """ Makes a response dictionary that is an error. """
+            if isinstance(e, ServiceException):
+                e = e._exc
             if isinstance(e, MethodNotFound):
                 c = -32601
             elif isinstance(e, PermissionError):
                 c = 403
+            elif isinstance(e, InvalidWikiPage):
+                c = 1
             elif isinstance(e, ResourceNotFound):
                 c = 404
+            elif isinstance(e, (QuerySyntaxError, QueryValueError)):
+                c = 400
+            elif isinstance(e, TracError):
+                c = -32500
+            elif isinstance(e, (EnvironmentError, MemoryError, SystemError)):
+                c = -32400
+            elif isinstance(e, NotImplementedError):
+                c = 501
             else:
                 c = c or hasattr(e, 'code') and e.code or -32603
             return {'result': None, 'id': r_id, 'error': {

trunk/tracrpc/util.py

     to_utimestamp = to_timestamp
     from_utimestamp = lambda x: to_datetime(x, utc)
 
+
 #--------------------------------------------------
 # Imported from TracGVizPlugin
 # needed for report, timeline and version control RPC

trunk/tracrpc/wiki.py

 from trac.attachment import Attachment
 from trac.core import *
 from trac.mimeview import Context
-from trac.resource import Resource, ResourceNotFound
+from trac.resource import Resource
 from trac.wiki.api import WikiSystem, IWikiPageManipulator
 from trac.wiki.model import WikiPage
 from trac.wiki.formatter import wiki_to_html, format_to_html
+from trac.wiki.web_ui import InvalidWikiPage
 
 from tracrpc.api import IXMLRPCHandler, expose_rpc, Binary
 from tracrpc.util import StringIO, to_utimestamp, from_utimestamp
             msg = 'Wiki page "%s" does not exist' % pagename
             if version is not None:
                 msg += ' at version %s' % version
-            raise ResourceNotFound(msg)
+            raise InvalidWikiPage(msg)
 
     def _page_info(self, name, when, author, version, comment):
         return dict(name=name, lastModified=when,
         
         Use this method if you don't care about WikiRPC compatibility. """
         if not WikiPage(self.env, pagename).exists:
-            raise ResourceNotFound, 'Wiki page "%s" does not exist' % pagename
+            raise InvalidWikiPage, 'Wiki page "%s" does not exist' % pagename
         if replace:
             try:
                 attachment = Attachment(self.env, 'wiki', pagename, filename)
         """ Delete an attachment. """
         pagename, filename = os.path.split(path)
         if not WikiPage(self.env, pagename).exists:
-            raise ResourceNotFound, 'Wiki page "%s" does not exist' % pagename
+            raise InvalidWikiPage, 'Wiki page "%s" does not exist' % pagename
         attachment = Attachment(self.env, 'wiki', pagename, filename)
         req.perm(attachment.resource).require('ATTACHMENT_DELETE')
         attachment.delete()

trunk/tracrpc/xml_rpc.py

 from trac.core import *
 from trac.perm import PermissionError
 from trac.resource import ResourceNotFound
+from trac.ticket.query import QuerySyntaxError, QueryValueError
 from trac.util.datefmt import utc
 from trac.util.text import to_unicode
 from trac.web.api import RequestDone
+from trac.wiki.web_ui import InvalidWikiPage
 
 from tracrpc.api import XMLRPCSystem, IRPCProtocol, Binary, \
         RPCError, MethodNotFound, ProtocolException, ServiceException
         """Send an XML-RPC fault message back to the caller"""
         rpcreq = req.rpc
         fault = None
+        # FIXME: Reusable and efficient
+        if isinstance(e, ServiceException):
+            e = e._exc
         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, InvalidWikiPage):
+            fault = xmlrpclib.Fault(1, to_unicode(e))
         elif isinstance(e, ResourceNotFound):
             fault = xmlrpclib.Fault(404, to_unicode(e))
+        elif isinstance(e, (QuerySyntaxError, QueryValueError)):
+            fault = xmlrpclib.Fault(400, to_unicode(e))
+        elif isinstance(e, TracError):
+            fault = xmlrpclib.Fault(-32500, to_unicode(e))
+        elif isinstance(e, (EnvironmentError, MemoryError, SystemError)):
+            fault = xmlrpclib.Fault(-32400, to_unicode(e))
+        elif isinstance(e, NotImplementedError):
+            fault = xmlrpclib.Fault(501, to_unicode(e))
 
         if fault is not None :
             self._send_response(req, xmlrpclib.dumps(fault), rpcreq['mimetype'])
             out = StringIO()
             traceback.print_exc(file = out)
             self.log.error(out.getvalue())
-            err_code = hasattr(e, 'code') and e.code or 1
+            err_code = hasattr(e, 'code') and e.code or -32603
             method = rpcreq.get('method')
             self._send_response(req,
                     xmlrpclib.dumps(
                         xmlrpclib.Fault(err_code,
-                            "'%s' while executing '%s()'" % (str(e), method))))
+                            "'%s' while executing '%s()'" % (to_unicode(e), 
+                                                             method))))
 
     # Internal methods