[dev] Horde_RPC_soap tweaks

John Morrissey jwm at horde.net
Mon Dec 17 18:34:38 UTC 2007


On Wed, Nov 28, 2007 at 11:24:18PM -0500, Chuck Hagenbuch wrote:
> Quoting John Morrissey <jwm at horde.net>:
> 
> > > Did you try setting the available methods explicitly in the 'provides'
> > > settings in registry.php instead?
> >
> > Yup. However, Horde_RPC_soap calls Registry::listMethods() with no
> > arguments, so all methods are listed.
> 
> Seems like a bug - if there are explicit provides entries, we  
> shouldn't return other methods, right?

Sorry, I wasn't clear. Registry::listMethods() honors provides entries, but
since it's called with no arguments in Horde_RPC_soap, the provided methods
for all applications are listed. This makes complete sense for the main
Horde WSDL, since you want to emit all possible provided methods.

> > > Yeah. I guess after thinking about this, I'd rather you passed an
> > > explicit array of allowed methods in the RPC constructor params
> > > instead of using a regex. The regex just feels hackish to me, but
> > > creating a limited server doesn't. How does that sound?
> >
> > That sounds decent, unless we decide on a straightforward way of
> > specifying API method visibility in api.php (above).
> 
> I think instantiating a limited server is still a useful feature.

I've made the suggestions to date; attached are the updated patches, for
HEAD and FRAMEWORK_3. Any final thoughts before I commit them?

> > > And is there any reason why you use global vars instead of object
> > > properties?
> >
> > I tried object properties initially, but it seems that something was
> > operating on a copy of the Horde_RPC_soap instance, so the data set in
> > Horde_RPC_soap::_dispatcher() never made it to
> > Horde_RPC_soap::getResponse() for logging. I suspect something in the
> > PEAR SOAP code, but wasn't able to find where.
> 
> Are you using PHP 4? It's possible we're missing a reference  
> somewhere, or that PEAR SOAP is, but with PHP 5 that shouldn't be an  
> issue.

nod, this is running on PHP 4. I'm fairly sure the missing reference is in
PEAR SOAP, since Horde's RPC implementation looks like it's handling this
properly AFAICT.

john
-- 
John Morrissey          _o            /\         ----  __o
jwm at horde.net        _-< \_          /  \       ----  <  \,
www.horde.net/    __(_)/_(_)________/    \_______(_) /_(_)__
-------------- next part --------------
Index: soap.php
===================================================================
RCS file: /repository/framework/RPC/RPC/soap.php,v
retrieving revision 1.24
diff -u -u -r1.24 soap.php
--- soap.php	2 Jan 2007 12:47:23 -0000	1.24
+++ soap.php	17 Dec 2007 18:11:50 -0000
@@ -24,6 +24,27 @@
     var $_server;
 
     /**
+     * List of types to emit in the WSDL.
+     *
+     * @var array
+     */
+    var $_restrictTypes = array();
+
+    /**
+     * List of method names to allow.
+     *
+     * @var array
+     */
+    var $_restrictCalls = array();
+
+    /**
+     * Name of the SOAP service to use in the WSDL.
+     *
+     * @var string
+     */
+    var $_serviceName = null;
+
+    /**
      * Hash holding all methods' signatures.
      *
      * @var array
@@ -39,6 +60,16 @@
     {
         parent::Horde_RPC($params);
 
+        if (!empty($params['restrictTypes'])) {
+            $this->_restrictTypes = $params['restrictTypes'];
+        }
+        if (!empty($params['restrictCalls'])) {
+            $this->_restrictCalls = $params['restrictCalls'];
+        }
+        if (!empty($params['serviceName'])) {
+            $this->_serviceName = $params['serviceName'];
+        }
+
         require_once 'SOAP/Server.php';
         $this->_server = new SOAP_Server();
         $this->_server->_auto_translation = true;
@@ -58,6 +89,10 @@
             if (!is_array($signature)) {
                 continue;
             }
+            if (!empty($this->_restrictCalls) &&
+                !in_array($method, $this->_restrictCalls)) {
+                continue;
+            }
             $method = str_replace('/', '.', $method);
             $this->__dispatch_map[$method] = array(
                 'in' => $signature[0],
@@ -65,7 +100,15 @@
             );
         }
 
-        $this->__typedef = $registry->listTypes();
+        $this->__typedef = array();
+        foreach ($registry->listTypes() as $type => $params) {
+            if (!empty($this->_restrictTypes) &&
+                !in_array($type, $this->_restrictTypes)) {
+                continue;
+            }
+
+            $this->__typedef[$type] = $params;
+        }
     }
 
     /**
@@ -107,6 +150,15 @@
         global $registry;
         $method = str_replace('.', '/', $method);
 
+        if (!empty($this->_params['restrictCalls']) &&
+            !in_array($method, $this->_params['restrictCalls'])) {
+            return sprintf(_("Method \"%s\" is not defined"), $method);
+        }
+
+        $GLOBALS['__horde_rpc_soap']['lastMethodCalled'] = $method;
+        $GLOBALS['__horde_rpc_soap']['lastMethodParams'] =
+            !empty($params) ? $params : array();
+
         if (!$registry->hasMethod($method)) {
             return sprintf(_("Method \"%s\" is not defined"), $method);
         }
@@ -128,7 +180,8 @@
 
         if ($request == 'disco' || $request == 'wsdl') {
             require_once 'SOAP/Disco.php';
-            $disco = new SOAP_DISCO_Server($this->_server, 'horde');
+            $disco = new SOAP_DISCO_Server($this->_server,
+                !empty($this->_serviceName) ? $this->_serviceName : 'horde');
             if ($request == 'wsdl') {
                 $this->_setupDispatchMap();
                 return $disco->getWSDL();
@@ -140,8 +193,19 @@
         $this->_server->setCallHandler(array($this, '_dispatcher'));
 
         /* We can't use Util::bufferOutput() here for some reason. */
+        $beginTime = time();
         ob_start();
         $this->_server->service($request);
+        Horde::logMessage(
+            sprintf(_("SOAP call: %s(%s) by %s serviced in %d seconds, sent %d bytes in response"),
+                $GLOBALS['__horde_rpc_soap']['lastMethodCalled'],
+                join(', ', array_map(
+                    create_function('$a', 'return is_array($a) ? "Array" : $a;'),
+                    $GLOBALS['__horde_rpc_soap']['lastMethodParams']
+                )),
+                Auth::getAuth(), time() - $beginTime, strlen($output)
+            ), __FILE__, __LINE__, PEAR_LOG_INFO
+        );
         return ob_get_clean();
     }
 
-------------- next part --------------
Index: soap.php
===================================================================
RCS file: /repository/framework/RPC/RPC/soap.php,v
retrieving revision 1.13.10.10
diff -u -u -r1.13.10.10 soap.php
--- soap.php	2 Jan 2007 13:54:36 -0000	1.13.10.10
+++ soap.php	17 Dec 2007 18:11:45 -0000
@@ -24,6 +24,27 @@
     var $_server;
 
     /**
+     * List of types to emit in the WSDL.
+     *
+     * @var array
+     */
+    var $_restrictTypes = array();
+
+    /**
+     * List of method names to allow.
+     *
+     * @var array
+     */
+    var $_restrictCalls = array();
+
+    /**
+     * Name of the SOAP service to use in the WSDL.
+     *
+     * @var string
+     */
+    var $_serviceName = null;
+
+    /**
      * Hash holding all methods' signatures.
      *
      * @var array
@@ -48,6 +69,15 @@
                 if (!empty($params['wsdl']) || !empty($params['disco'])) {
                     $this->_authorize = false;
                 }
+                if (!empty($params['restrictTypes'])) {
+                    $this->_restrictTypes = $params['restrictTypes'];
+                }
+                if (!empty($params['restrictCalls'])) {
+                    $this->_restrictCalls = $params['restrictCalls'];
+                }
+                if (!empty($params['serviceName'])) {
+                    $this->_serviceName = $params['serviceName'];
+                }
             }
         }
 
@@ -72,6 +102,10 @@
             if (!is_array($signature)) {
                 continue;
             }
+            if (!empty($this->_restrictCalls) &&
+                !in_array($method, $this->_restrictCalls)) {
+                continue;
+            }
             $method = str_replace('/', '.', $method);
             $this->__dispatch_map[$method] = array(
                 'in' => $signature[0],
@@ -79,7 +113,15 @@
             );
         }
 
-        $this->__typedef = $registry->listTypes();
+        $this->__typedef = array();
+        foreach ($registry->listTypes() as $type => $params) {
+            if (!empty($this->_restrictTypes) &&
+                !in_array($type, $this->_restrictTypes)) {
+                continue;
+            }
+
+            $this->__typedef[$type] = $params;
+        }
     }
 
     /**
@@ -121,6 +163,15 @@
         global $registry;
         $method = str_replace('.', '/', $method);
 
+        if (!empty($this->_params['restrictCalls']) &&
+            !in_array($method, $this->_params['restrictCalls'])) {
+            return sprintf(_("Method \"%s\" is not defined"), $method);
+        }
+
+        $GLOBALS['__horde_rpc_soap']['lastMethodCalled'] = $method;
+        $GLOBALS['__horde_rpc_soap']['lastMethodParams'] =
+            !empty($params) ? $params : array();
+
         if (!$registry->hasMethod($method)) {
             return sprintf(_("Method \"%s\" is not defined"), $method);
         }
@@ -143,16 +194,30 @@
     {
         $this->_server->addObjectMap($this, 'urn:horde');
 
-        if (!$params) {
+        if (!$params ||
+            (is_array($params) &&
+             empty($params['disco']) && empty($params['wsdl']))) {
             $this->_server->setCallHandler(array($this, '_dispatcher'));
             /* We can't use Util::bufferOutput() here for some reason. */
+            $beginTime = time();
             ob_start();
             $this->_server->service($request);
             $output = ob_get_contents();
+            Horde::logMessage(
+                sprintf(_("SOAP call: %s(%s) by %s serviced in %d seconds, sent %d bytes in response"),
+                    $GLOBALS['__horde_rpc_soap']['lastMethodCalled'],
+                    join(', ', array_map(
+                        create_function('$a', 'return is_array($a) ? "Array" : $a;'),
+                        $GLOBALS['__horde_rpc_soap']['lastMethodParams']
+                    )),
+                    Auth::getAuth(), time() - $beginTime, strlen($output)
+                ), __FILE__, __LINE__, PEAR_LOG_INFO
+            );
             ob_end_clean();
         } else {
             require_once 'SOAP/Disco.php';
-            $disco = new SOAP_DISCO_Server($this->_server, 'horde');
+            $disco = new SOAP_DISCO_Server($this->_server,
+                !empty($this->_serviceName) ? $this->_serviceName : 'horde');
             // BC: $params should be an array, but until 3.1.4 $params
             //     required a string here.
             if ((is_string($params) && $params == 'wsdl') ||


More information about the dev mailing list