[Zope3-checkins] SVN: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/ Allow XML-RPC view methods to take parameters.

Philipp von Weitershausen philikon at philikon.de
Sun Aug 29 14:15:59 EDT 2004


Log message for revision 27332:
  Allow XML-RPC view methods to take parameters.
  
  When the XML-RPC view setup machinery was changed recently, views taking parameters
  were not tested.  The problem was that methods were security protected using
  an instance of ProtectedMethod which implemented ILocation (thus could inherit
  security context) and provides a __call__(*args) and passes *args onto the
  actual view method.  THis works fine when no parameters are issues via xml-rpc,
  but when they are, zope.publisher.publish.mapply chokes.  For some reason, it
  cannot figure out the *args thing.
  
  This fix gets rid of MethodFactory and ProtectedMethod.  Instead, a new view
  class with a security checker and a __call__ that is a copy of the method that
  is to be used is created.  This process is very similar to what happens with
  browser pages.
  
  README.txt was updated with a functional test for this.
  


Changed:
  U   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt
  U   Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/metaconfigure.py


-=-
Modified: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt	2004-08-29 18:02:19 UTC (rev 27331)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/README.txt	2004-08-29 18:15:59 UTC (rev 27332)
@@ -245,6 +245,72 @@
   </methodResponse>
   <BLANKLINE>
 
+Parameters
+----------
+
+Of course, XML-RPC views can take parameters, too:
+
+  >>> class ParameterDemo:
+  ...     def __init__(self, context, request):
+  ...         self.context = context
+  ...         self.request = request
+  ...
+  ...     def add(self, first, second):
+  ...         return first + second
+
+Now we'll register it as a view:
+
+  >>> from zope.configuration import xmlconfig
+  >>> ignored = xmlconfig.string("""
+  ... <configure 
+  ...     xmlns="http://namespaces.zope.org/zope"
+  ...     xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
+  ...     >
+  ...   <!-- We only need to do this include in this example, 
+  ...        Normally the include has already been done for us. -->
+  ...   <include package="zope.app.publisher.xmlrpc" file="meta.zcml" />
+  ...
+  ...   <xmlrpc:view
+  ...       for="zope.app.folder.folder.IFolder"
+  ...       methods="add"
+  ...       class="zope.app.publisher.xmlrpc.README.ParameterDemo"
+  ...       permission="zope.ManageContent"
+  ...       />
+  ... </configure>
+  ... """)
+
+Then we can issue a remote procedure call with a parameter and get
+back, surprise!, the sum:
+
+  >>> print http(r"""
+  ... POST / HTTP/1.0
+  ... Authorization: Basic bWdyOm1ncnB3
+  ... Content-Length: 159
+  ... Content-Type: text/xml
+  ... 
+  ... <?xml version='1.0'?>
+  ... <methodCall>
+  ... <methodName>add</methodName>
+  ... <params>
+  ... <param><int>20</int></param>
+  ... <param><int>22</int></param>
+  ... </params>
+  ... </methodCall>
+  ... """, handle_errors=False)
+  HTTP/1.0 200 Ok
+  Content-Length: 122
+  Content-Type: text/xml;charset=utf-8
+  <BLANKLINE>
+  <?xml version='1.0'?>
+  <methodResponse>
+  <params>
+  <param>
+  <value><int>42</int></value>
+  </param>
+  </params>
+  </methodResponse>
+  <BLANKLINE>
+
 Faults
 ------
 

Modified: Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/metaconfigure.py
===================================================================
--- Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/metaconfigure.py	2004-08-29 18:02:19 UTC (rev 27331)
+++ Zope3/branches/ZopeX3-3.0/src/zope/app/publisher/xmlrpc/metaconfigure.py	2004-08-29 18:15:59 UTC (rev 27332)
@@ -15,18 +15,16 @@
 
 $Id$
 """
-
+import zope.interface
+from zope.security.checker import CheckerPublic, Checker
 from zope.component.servicenames import Presentation
 from zope.configuration.exceptions import ConfigurationError
-from zope.app.component.metaconfigure import handler
-import zope.interface
-
 from zope.publisher.interfaces.xmlrpc import IXMLRPCRequest
-from zope.security.checker import CheckerPublic, Checker
+
+from zope.app.location import Location
 from zope.app.component.interface import provideInterface
+from zope.app.component.metaconfigure import handler
 
-import zope.app.location
-
 def view(_context, for_=None, interface=None, methods=None,
          class_=None,  permission=None, name=None):
     
@@ -77,14 +75,19 @@
             checker = Checker({'__call__': permission})
         else:
             checker = None
-            
+
         for name in require:
+            # create a new callable class with a security checker; mix
+            # in zope.app.location.Location so that the view inherits
+            # a security context
+            cdict = {'__Security_checker__': checker,
+                     '__call__': getattr(class_, name)}
+            new_class = type(class_.__name__, (class_, Location), cdict)
             _context.action(
                 discriminator = ('view', for_, name, IXMLRPCRequest),
                 callable = handler,
                 args = (Presentation, 'provideAdapter', IXMLRPCRequest,
-                        MethodFactory(class_, name, checker),
-                        name, (for_, )) )
+                        new_class, name, (for_, )) )
 
     # Register the used interfaces with the interface service
     if for_ is not None:
@@ -93,32 +96,3 @@
             callable = provideInterface,
             args = ('', for_)
             )
-        
-
-
-class MethodFactory:
-
-    def __init__(self, cls, name, checker):
-        self.cls, self.name, self.checker = cls, name, checker
-
-    def __call__(self, context, request):
-        ob = self.cls(context, request)
-        ob = getattr(ob, self.name)
-        if self.checker is not None:
-            ob = ProtectedMethod(ob, self.checker)
-        return ob
-
-
-class ProtectedMethod:
-
-    zope.interface.implements(zope.app.location.ILocation)
-
-    __parent__ = __name__ = None
-
-    def __init__(self, ob, checker):
-        self.ob = ob
-        self.__Security_checker__ = checker
-
-    def __call__(self, *args):
-        return self.ob(*args)
-    



More information about the Zope3-Checkins mailing list