[Checkins] SVN: z3c.jsonrpc/trunk/ - improve error handling
Roger Ineichen
roger at projekt01.ch
Sun Aug 23 16:10:31 EDT 2009
Log message for revision 103118:
- improve error handling
- implemented error views concept given from ZopePublication
- removed old SETUP.cfg and friends
- adjust error test
Changed:
U z3c.jsonrpc/trunk/CHANGES.txt
U z3c.jsonrpc/trunk/setup.py
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/README.txt
D z3c.jsonrpc/trunk/src/z3c/jsonrpc/SETUP.cfg
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/configure.zcml
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.py
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.zcml
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/exception.py
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/interfaces.py
U z3c.jsonrpc/trunk/src/z3c/jsonrpc/publisher.py
D z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-configure.zcml
D z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-meta.zcml
-=-
Modified: z3c.jsonrpc/trunk/CHANGES.txt
===================================================================
--- z3c.jsonrpc/trunk/CHANGES.txt 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/CHANGES.txt 2009-08-23 20:10:31 UTC (rev 103118)
@@ -2,6 +2,20 @@
CHANGES
=======
+0.6.0 (unreleased)
+------------------
+
+- implemented error view concept which will work with ZopePublication
+
+- implemented default error view for known zope and JSON-RPC errors
+
+- use DirectResult in response
+
+- removed unauthenticated error view. This was not working and requires a
+ custom concept supported by the used java script library used at client
+ side
+
+
Version 0.5.4 (2009-04-07)
--------------------------
Modified: z3c.jsonrpc/trunk/setup.py
===================================================================
--- z3c.jsonrpc/trunk/setup.py 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/setup.py 2009-08-23 20:10:31 UTC (rev 103118)
@@ -24,7 +24,7 @@
setup (
name='z3c.jsonrpc',
- version='0.5.4',
+ version='0.6.0dev',
author = "Roger Ineichen and the Zope Community",
author_email = "zope-dev at zope.org",
description = "JSON RPC server and client implementation for Zope3",
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/README.txt
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/README.txt 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/README.txt 2009-08-23 20:10:31 UTC (rev 103118)
@@ -400,17 +400,18 @@
Error handling
--------------
-See what happens if the server raises an Exception:
+See what happens if the server raises an Exception. We will get a response
+error with additional error content:
>>> proxy.forceValueError()
Traceback (most recent call last):
...
ResponseError: Check proxy.error for error message
-and the error message is:
+and the error content looks like:
>>> proxy.error
- {u'message': u'Invalid JSON-RPC', u'code': -32603, u'data': u'ValueError: Something was wrong in server method.'}
+ {u'message': u'Internal error', u'code': -32603, u'data': {u'i18nMessage': u'Internal error'}}
The error property gets reset on the next successfull call:
Deleted: z3c.jsonrpc/trunk/src/z3c/jsonrpc/SETUP.cfg
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/SETUP.cfg 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/SETUP.cfg 2009-08-23 20:10:31 UTC (rev 103118)
@@ -1,3 +0,0 @@
-<data-files zopeskel/etc/package-includes>
- z3c.jsonrpc-*.zcml
-</data-files>
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/configure.zcml
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/configure.zcml 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/configure.zcml 2009-08-23 20:10:31 UTC (rev 103118)
@@ -49,12 +49,15 @@
permission="zope.Public"
/>
- <!-- Be careful and register the skin namespace for our request and layer.
- This will prevents that we can simply get the wrong skin namespace
- based on the __iro__ order of our layer and request interfaces.
- Note, if we don't choose carefully our layer and request interfaces
- for our skin, it's possible that we get the skin namespace registered
- for the browser request -->
+ <!-- If you register your own layer and skin setup, be careful and register
+ the skin namespace below for our JSON-RPC layer. This will prevents
+ that you will get the wrong skin namespace based on the __iro__ order of
+ the layer interfaces.
+
+ Since JSON-RPC supports layers and skins it's highly recommended not to
+ mix IJSONRPCLayer and IBrowserRequest layers. Otherwise you have to make
+ sure that the right default skin interface get applied.
+ -->
<adapter
name="skin"
factory=".namespace.skin"
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.py
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.py 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.py 2009-08-23 20:10:31 UTC (rev 103118)
@@ -20,14 +20,100 @@
_ = zope.i18nmessageid.MessageFactory('z3c')
+from z3c.jsonrpc import interfaces
-class UnauthorizedResponse(object):
- """Knows how to return error content."""
+# The error codes used since JSON-RPC 2.0
+# See: http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal
+#
+# code message Meaning
+# --------------------------------
+# -32700 Parse error. Invalid JSON. An error occurred on the server
+# while parsing the JSON text.
+# -32600 Invalid Request. The received JSON not a valid JSON-RPC Request.
+# -32601 Method not found. The requested remote-procedure does not exist,
+# is not available.
+# -32602 Invalid params. Invalid method parameters.
+# -32603 Internal error. Internal JSON-RPC error.
+# -32099..-32000 Server error. Reserved for implementation-defined server-errors.
+
+class JSONRPCErrorView(object):
+ """Generic JSON-RPC error view.
+
+ This base class is used for error views which are used for error handling
+ by ZopePublication.
+ """
+
+ zope.interface.implements(interfaces.IJSONRPCErrorView)
+
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
- errMsg = _('You are not allowed to access this content.')
- return zope.i18n.translate(errMsg, context=self.request)
+ """Must return itself.
+
+ This allows us to use the error view in setResult if ZopePublication
+ is adapting an error view to error and request and calls them.
+ """
+ return self
+
+
+class ParseErrorView(JSONRPCErrorView):
+ """Knows the error data for parse errors."""
+
+ code = -32700
+ message = u'Parse error'
+
+ @property
+ def data(self):
+ errMsg = _('Parse error')
+ return {'i18nMessage':zope.i18n.translate(errMsg, context=self.request)}
+
+
+class InvalidRequestErrorView(JSONRPCErrorView):
+ """Knows the error data for invalid request errors."""
+
+ code = -32600
+ message = u'Invalid Request'
+
+ @property
+ def data(self):
+ errMsg = _('Invalid Request')
+ return {'i18nMessage':zope.i18n.translate(errMsg, context=self.request)}
+
+
+class MethodNotFoundView(JSONRPCErrorView):
+ """Knows the error data for NotFound errors."""
+
+ code = -32601
+ message = u'Method not found'
+
+ @property
+ def data(self):
+ errMsg = _('Method not found')
+ return {'i18nMessage':zope.i18n.translate(errMsg, context=self.request)}
+
+
+class InvalidParamsErrorView(JSONRPCErrorView):
+ """Knows the error data for invalid params errors."""
+
+ code = -32602
+ message = u'Invalid params'
+
+ @property
+ def data(self):
+ errMsg = _('Invalid params')
+ return {'i18nMessage':zope.i18n.translate(errMsg, context=self.request)}
+
+
+class InternalErrorView(JSONRPCErrorView):
+ """Knows the error data for invalid params errors."""
+
+ code = -32603
+ message = u'Internal error'
+
+ @property
+ def data(self):
+ errMsg = _('Internal error')
+ return {'i18nMessage':zope.i18n.translate(errMsg, context=self.request)}
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.zcml
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.zcml 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/error.zcml 2009-08-23 20:10:31 UTC (rev 103118)
@@ -3,41 +3,102 @@
xmlns="http://namespaces.zope.org/browser"
i18n_domain="z3c">
- <!-- implement error views for this exceptions
- The error views should return a 1i8n aware error message as result
- which get set in setResult instead of using the built in
- handleException form the JSONRPCResponse.
- See zope.app.publication.zopepublication.ZopePublication
- -->
- <defaultView
+ <!-- zope error views used by ZopePublication -->
+ <page
name="error"
+ class=".error.InternalErrorView"
for="zope.interface.common.interfaces.IException"
layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
/>
-
- <defaultView
+ <page
name="error"
+ class=".error.MethodNotFoundView"
+ for="zope.publisher.interfaces.INotFound"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <page
+ name="error"
+ class=".error.MethodNotFoundView"
for="zope.publisher.interfaces.ITraversalException"
layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
/>
+ <page
+ name="error"
+ class=".error.InternalErrorView"
+ for="zope.exceptions.interfaces.IUserError"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
- <!-- IUnauthorized -->
+
+ <!-- JSON-RPC error views used by ZopePublication -->
<page
name="error"
- class=".error.UnauthorizedResponse"
- for="zope.security.interfaces.IUnauthorized"
+ class=".error.InternalErrorView"
+ for=".interfaces.IJSONRPCException"
layer="z3c.jsonrpc.layer.IJSONRPCLayer"
permission="zope.Public"
/>
+ <page
+ name="error"
+ class=".error.ParseErrorView"
+ for=".exception.ParseError"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <page
+ name="error"
+ class=".error.InvalidRequestErrorView"
+ for=".exception.InvalidRequest"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <page
+ name="error"
+ class=".error.MethodNotFoundView"
+ for=".exception.MethodNotFound"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <page
+ name="error"
+ class=".error.InvalidParamsErrorView"
+ for=".exception.InvalidParams"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <page
+ name="error"
+ class=".error.InternalErrorView"
+ for=".exception.InternalError"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ permission="zope.Public"
+ />
+ <!-- default view names -->
<defaultView
name="error"
- for="zope.security.interfaces.IUnauthorized"
+ for=".interfaces.IJSONRPCException"
layer="z3c.jsonrpc.layer.IJSONRPCLayer"
/>
<defaultView
name="error"
+ for="zope.interface.common.interfaces.IException"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ />
+
+ <defaultView
+ name="error"
+ for="zope.publisher.interfaces.ITraversalException"
+ layer="z3c.jsonrpc.layer.IJSONRPCLayer"
+ />
+
+ <defaultView
+ name="error"
for="zope.exceptions.interfaces.IUserError"
layer="z3c.jsonrpc.layer.IJSONRPCLayer"
/>
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/exception.py
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/exception.py 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/exception.py 2009-08-23 20:10:31 UTC (rev 103118)
@@ -15,24 +15,16 @@
$Id:$
"""
+import zope.interface
+from z3c.jsonrpc import interfaces
-# The error codes used since JSON-RPC 2.0:
-#
-# code message Meaning
-# --------------------------------
-# -32700 Parse error. Invalid JSON. An error occurred on the server
-# while parsing the JSON text.
-# -32600 Invalid Request. The received JSON not a valid JSON-RPC Request.
-# -32601 Method not found. The requested remote-procedure does not exist,
-# is not available.
-# -32602 Invalid params. Invalid method parameters.
-# -32603 Internal error. Internal JSON-RPC error.
-# -32099..-32000 Server error. Reserved for implementation-defined server-errors.
class JSONRPCException(Exception):
"""Base class for JSON-RPC exception."""
+ zope.interface.implements(interfaces.IJSONRPCException)
+
class ParseError(JSONRPCException):
"""Invalid JSON. An error occurred on the server while parsing the JSON text."""
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/interfaces.py
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/interfaces.py 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/interfaces.py 2009-08-23 20:10:31 UTC (rev 103118)
@@ -16,6 +16,7 @@
"""
__docformat__ = "reStructuredText"
+import zope.schema
import zope.interface
from zope.publisher.interfaces import IPublication
from zope.publisher.interfaces import IPublishTraverse
@@ -60,3 +61,36 @@
"""JSON-RPC request."""
jsonID = zope.interface.Attribute("""JSON-RPC ID for the request""")
+
+
+class IJSONRPCException(zope.interface.Interface):
+ """JSON-RPC error"""
+
+
+class IJSONRPCErrorView(zope.interface.Interface):
+ """Error view base class used by ZopePublications error handling.
+ """
+
+ code = zope.schema.Int(
+ title=u'Error code',
+ description=u'JSON-RPC error code',
+ default=-32603,
+ required=True)
+
+ message = zope.schema.Text(
+ title=u'Error message',
+ description=u'JSON-RPC error message',
+ default=u'Internal error',
+ required=True)
+
+ data = zope.schema.Text(
+ title=u'Error data',
+ description=u'JSON-RPC error data',
+ default=u'',
+ required=True)
+
+ def __init__(self):
+ """Adapts an error and a request."""
+
+ def __call__(self):
+ """Must return itself by calling."""
Modified: z3c.jsonrpc/trunk/src/z3c/jsonrpc/publisher.py
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/publisher.py 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/publisher.py 2009-08-23 20:10:31 UTC (rev 103118)
@@ -28,6 +28,7 @@
from zope.publisher.http import HTTPRequest
from zope.publisher.http import HTTPResponse
from zope.publisher.http import getCharsetUsingRequest
+from zope.publisher.http import DirectResult
from zope.security.proxy import isinstance
from z3c.json.interfaces import IJSONReader
@@ -264,7 +265,6 @@
class JSONRPCResponse(HTTPResponse):
"""JSON-RPC Response"""
-
def setResult(self, result):
"""The result dict contains the following key value pairs
@@ -286,19 +286,50 @@
"""
jsonId = self._request.jsonId
jsonVersion = self._request.jsonVersion
- result = premarshal(result)
- if jsonVersion == "1.0":
- wrapper = {'result': result, 'error': None, 'id': jsonId}
- elif jsonVersion == "1.1":
- wrapper = {'version': jsonVersion, 'result': result, 'id': jsonId}
+
+ if interfaces.IJSONRPCErrorView.providedBy(result):
+ if self._request.jsonVersion == "1.0":
+ wrapper = {'result': None,
+ 'error': result.message,
+ 'id': self._request.jsonId}
+ elif self._request.jsonVersion == "1.1":
+ wrapper = {'version': self._request.jsonVersion,
+ 'error': result.message,
+ 'id': self._request.jsonId}
+ else:
+ wrapper = {'jsonrpc': self._request.jsonVersion,
+ 'error': {'code': result.code,
+ 'message': result.message,
+ 'data': result.data},
+ 'id': self._request.jsonId}
+
+ try:
+ json = zope.component.getUtility(IJSONWriter)
+ result = json.write(wrapper)
+ body = self._prepareResult(result)
+ super(JSONRPCResponse, self).setResult(DirectResult((body,)))
+ logger.log(DEBUG, "Exception: %s" % result)
+ # error response is not really an error, it's valid response
+ self.setStatus(200)
+ except:
+ # Catch all exceptions at this point
+ self.handleException(sys.exc_info())
+ return
+
else:
- wrapper = {'jsonrpc': jsonVersion, 'result': result, 'id': jsonId}
- json = zope.component.getUtility(IJSONWriter)
- encoding = getCharsetUsingRequest(self._request)
- result = json.write(wrapper)
- body = self._prepareResult(result)
- super(JSONRPCResponse,self).setResult(body)
- logger.log(DEBUG, "%s" % result)
+ result = premarshal(result)
+ if jsonVersion == "1.0":
+ wrapper = {'result': result, 'error': None, 'id': jsonId}
+ elif jsonVersion == "1.1":
+ wrapper = {'version': jsonVersion, 'result': result, 'id': jsonId}
+ else:
+ wrapper = {'jsonrpc': jsonVersion, 'result': result, 'id': jsonId}
+ json = zope.component.getUtility(IJSONWriter)
+ encoding = getCharsetUsingRequest(self._request)
+ result = json.write(wrapper)
+ body = self._prepareResult(result)
+ super(JSONRPCResponse,self).setResult(DirectResult((body,)))
+ logger.log(DEBUG, "%s" % result)
def _prepareResult(self, result):
# we've asked json to return unicode; result should be unicode
@@ -320,6 +351,10 @@
return body
def handleException(self, exc_info):
+ # only legacy Exception where we didn't define a view for get handled
+ # by this method. All exceptions where we have a view registered for
+ # get handled by the setResult method based on the given
+ # IJSONRPCErrorView
t, value = exc_info[:2]
exc_data = []
for file, lineno, function, text in traceback.extract_tb(exc_info[2]):
@@ -332,15 +367,14 @@
if self._request.jsonVersion == "1.0":
wrapper = {'result': None,
'error': s,
- 'id': self._request.jsonId,}
+ 'id': self._request.jsonId}
elif self._request.jsonVersion == "1.1":
wrapper = {'version': self._request.jsonVersion,
'error': s,
- 'id': self._request.jsonId,}
+ 'id': self._request.jsonId}
else:
- # TODO: implement better error handling, use the right error codes.
- # see:
- # http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal#error-object
+ # this only happens if error handling was running into en error or
+ # if we didn't define an IJSONRPCErrorView for a given error
wrapper = {'jsonrpc': self._request.jsonVersion,
'error': {'code': -32603,
'message': 'Invalid JSON-RPC',
@@ -350,6 +384,6 @@
json = zope.component.getUtility(IJSONWriter)
result = json.write(wrapper)
body = self._prepareResult(result)
- super(JSONRPCResponse, self).setResult(body)
+ super(JSONRPCResponse, self).setResult(DirectResult((body,)))
logger.log(DEBUG, "Exception: %s" % result)
self.setStatus(200)
Deleted: z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-configure.zcml
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-configure.zcml 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-configure.zcml 2009-08-23 20:10:31 UTC (rev 103118)
@@ -1 +0,0 @@
-<include package="z3c.jsonrpc" />
Deleted: z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-meta.zcml
===================================================================
--- z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-meta.zcml 2009-08-23 19:54:32 UTC (rev 103117)
+++ z3c.jsonrpc/trunk/src/z3c/jsonrpc/z3c.jsonrpc-meta.zcml 2009-08-23 20:10:31 UTC (rev 103118)
@@ -1 +0,0 @@
-<include package="z3c.jsonrpc" file="meta.zcml" />
More information about the Checkins
mailing list