[Checkins] SVN: grokcore.rest/trunk/src/grokcore/rest/rest.py copying for getting the history

Christian Klinger cklinger at novareto.de
Mon Nov 8 06:11:54 EST 2010


Log message for revision 118283:
  copying for getting the history

Changed:
  A   grokcore.rest/trunk/src/grokcore/rest/rest.py

-=-
Copied: grokcore.rest/trunk/src/grokcore/rest/rest.py (from rev 118282, grok/trunk/src/grok/rest.py)
===================================================================
--- grokcore.rest/trunk/src/grokcore/rest/rest.py	                        (rev 0)
+++ grokcore.rest/trunk/src/grokcore/rest/rest.py	2010-11-08 11:11:53 UTC (rev 118283)
@@ -0,0 +1,108 @@
+"""Default REST view for Grok.
+
+The views provided by this module get invoked when an object receives an
+HTTP request in a REST skin for which no more-specific REST behavior has
+been defined.  These all return the HTTP response Method Not Allowed.
+
+"""
+import grok
+from grok.interfaces import IRESTSkinType
+
+from zope import component
+from zope.component.interfaces import ComponentLookupError
+from zope.traversing.interfaces import TraversalError
+from zope.traversing.namespace import view
+from zope.interface import Interface
+from zope.publisher.interfaces.http import IHTTPRequest
+from zope.app.publication.http import MethodNotAllowed
+from zope.publisher.browser import applySkin
+
+
+class GrokMethodNotAllowed(MethodNotAllowed):
+    """Exception indicating that an attempted REST method is not allowed."""
+
+
+class MethodNotAllowedView(grok.MultiAdapter):
+    """View rendering a REST GrokMethodNotAllowed exception over HTTP.
+
+    Not only does this view render the REST error as an HTTP status of
+    405 (Method Not Allowed) and a simple text message as the document
+    body, but also offers an ``Allow:`` HTTP header listing any methods
+    that can, in fact, succeed.  It constructs this list by testing the
+    current object to see which methods it supports; if none of the
+    standard methods succeed, then the ``Allow:`` header is still
+    provided, but its value will be empty.
+
+    """
+    grok.adapts(GrokMethodNotAllowed, IHTTPRequest)
+    grok.name('index.html')
+    grok.implements(Interface)
+
+    def __init__(self, error, request):
+        self.error = error
+        self.request = request
+        self.allow = self._getAllow()
+
+    def _getAllow(self):
+        allow = []
+        # List methods here in the same order that they should appear in
+        # the "Allow:" header.
+        for method in 'DELETE', 'GET', 'POST', 'PUT':
+            view = component.queryMultiAdapter(
+                (self.error.object, self.error.request),
+                name=method)
+            if view is not None:
+                is_not_allowed = getattr(view, 'is_not_allowed', False)
+                if not is_not_allowed:
+                    allow.append(method)
+        return allow
+
+    def __call__(self):
+        self.request.response.setHeader('Allow', ', '.join(self.allow))
+        self.request.response.setStatus(405)
+        return 'Method Not Allowed'
+
+
+class rest_skin(view):
+    """A rest skin.
+
+    This used to be supported by zope.traversing but the change was
+    backed out.  We need it for our REST support.
+
+    """
+    def traverse(self, name, ignored):
+        self.request.shiftNameToApplication()
+        try:
+            skin = component.getUtility(IRESTSkinType, name)
+        except ComponentLookupError:
+            raise TraversalError("++rest++%s" % name)
+        applySkin(self.request, skin)
+        return self.context
+
+
+class NotAllowedREST(grok.REST):
+    """Default REST view, whose methods all raise Not Allowed errors.
+
+    By binding itself to ``Interface``, this becomes the most general
+    available REST view, and will be called into service for objects
+    that have not had more specific REST views registered.  This means
+    that such objects can at least return attractive refusals when
+    clients attempt to assail them with unwanted HTTP methods.
+
+    """
+    grok.layer(grok.IRESTLayer)
+    grok.context(Interface)
+
+    is_not_allowed = True
+
+    def GET(self):
+        raise GrokMethodNotAllowed(self.context, self.request)
+
+    def POST(self):
+        raise GrokMethodNotAllowed(self.context, self.request)
+
+    def PUT(self):
+        raise GrokMethodNotAllowed(self.context, self.request)
+
+    def DELETE(self):
+        raise GrokMethodNotAllowed(self.context, self.request)



More information about the checkins mailing list