Skip to content
This repository has been archived by the owner on May 16, 2018. It is now read-only.

Zend_Rest_Server does not properly handle optional parameters when anonymous (arg1, etc) parameters are passed in #187

Closed
C-Duv opened this issue Aug 13, 2013 · 0 comments
Assignees
Milestone

Comments

@C-Duv
Copy link

C-Duv commented Aug 13, 2013

Note: Issue already reported by Jonathan Csanyi (jcsanyi) on 2010-03-08T17:49:13.000+0000 (see [ZF-9374])(http://framework.zend.com/issues/browse/ZF-9374) but isn't closed there and bug is still present in v1.12.3.

Related issues: #186

When anonymous parameters are passed in, and one or more optional parameters are missing, the default values are not correctly filled in, and the call fails with a 'missing arguments' error message.

Original comments

Posted by Jonathan Csanyi (jcsanyi) on 2010-03-08T17:51:19.000+0000

There was already a unit test for this functionality, but the expected value was incorrectly hard-coded backwards, so the failure was counting as a pass.


Posted by Jonathan Csanyi (jcsanyi) on 2010-03-08T17:53:36.000+0000

Attached patch fixes Zend_Rest_Server, and accompanying unit tests.


Posted by Jonathan Csanyi (jcsanyi) on 2010-03-08T18:00:28.000+0000

'sorry.. original diff had a misleading/incorrect comment. This is the correct diff.


Posted by Claude Duvergier (cduv) on 2010-07-15T03:23:47.000+0000

I agree with Jonathan Csanyi.

I ran into that problem an thought Zend_Rest_Client was the cause as it uses the "arg1" query parameter name when only one argument is passed to the server (see ZF-4910). But is seems that Zend_Rest_Server is guilty.

With the following server PHP code:

class MyServerImpl
{
  public function myMethod ($var)
  {
    $return $var*$var;
  }
  public function myOtherMethod ($var = 3)
  {
    $return $var*$var;
  }
}
$server = new Zend_Rest_Server();
$server->setClass('MyServerImpl');
$server->handle();

The following client PHP code:

$client
  ->myMethod(5)
  ->get();

Issues the following request: server.php?method=myMethod&myMethod=5&arg1=5

Which is handled by Zend_Rest_Server::handle() as

$missing_args[0] = 'var';
$calling_args[1] = 5
=> myMethod(5);

Which is correct.

And the other following client PHP code:

$client
  ->myOtherMethod(5)
  ->get();

Issues the following request: server.php?method=myOtherMethod&myOtherMethod=5&arg1=5

Which is handled by Zend_Rest_Server::handle() as

$missing_args[] = array();
$calling_args[0] = 3;
$calling_args[1] = 5;
=> myOtherMethod(3);

Which is incorrect.

The solution would be to either use 0-based array everywhere, or the given "library/Zend/Rest/Server.php" DIFF file "trunk-correct.diff".

Original attachments

trunk.diff

Index: tests/Zend/Rest/ServerTest.php
===================================================================
--- tests/Zend/Rest/ServerTest.php  (revision 21404)
+++ tests/Zend/Rest/ServerTest.php  (working copy)
@@ -542,9 +542,10 @@

     /**
      * @see ZF-1949
+     * @see ZF-9374
      * @group ZF-1949
      */
-    public function testMissingArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    public function testMissingAnonArgumentsWithDefaultsShouldNotResultInFaultResponse()
     {
         $server = new Zend_Rest_Server();
         $server->setClass('Zend_Rest_Server_Test');
@@ -552,10 +553,38 @@
         $server->handle(array('method' => 'testFunc7', 'arg1' => "Davey"));
         $result = ob_get_clean();
         $this->assertContains('<status>success</status>', $result, var_export($result, 1));
-        $this->assertContains('<response>Hello today, How are you Davey</response>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
     }

     /**
+     * @see ZF-9374
+     */
+    public function testMissingZeroBasedAnonArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    {
+        $server = new Zend_Rest_Server();
+        $server->setClass('Zend_Rest_Server_Test');
+        ob_start();
+        $server->handle(array('method' => 'testFunc7', 'arg0' => "Davey"));
+        $result = ob_get_clean();
+        $this->assertContains('<status>success</status>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
+    }
+
+    /**
+     * @see ZF-9374
+     */
+    public function testMissingNamesArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    {
+        $server = new Zend_Rest_Server();
+        $server->setClass('Zend_Rest_Server_Test');
+        ob_start();
+        $server->handle(array('method' => 'testFunc7', 'who' => "Davey"));
+        $result = ob_get_clean();
+        $this->assertContains('<status>success</status>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
+    }
+
+    /**
      * @group ZF-3751
      */
     public function testCallingUnknownMethodDoesNotThrowUnknownButSpecificErrorExceptionMessage()
Index: library/Zend/Rest/Server.php
===================================================================
--- library/Zend/Rest/Server.php    (revision 21404)
+++ library/Zend/Rest/Server.php    (working copy)
@@ -189,28 +189,35 @@

                     $func_args = $this->_functions[$this->_method]->getParameters();

+                    // calling_args will be a zero-based array of the parameters
                     $calling_args = array();
                     $missing_args = array();
-                    foreach ($func_args as $arg) {
+                    foreach ($func_args as $i => $arg) {
                         if (isset($request[strtolower($arg->getName())])) {
-                            $calling_args[] = $request[strtolower($arg->getName())];
+                            $calling_args[$i] = $request[strtolower($arg->getName())];
                         } elseif ($arg->isOptional()) {
-                            $calling_args[] = $arg->getDefaultValue();
+                            $calling_args[$i] = $arg->getDefaultValue();
                         } else {
                             $missing_args[] = $arg->getName();
                         }
                     }

+                    // anon_args may be zero-based (per docs), or 1-based (per incorrect Zend_Rest_Client @see ZF-9373)
+                    $anon_args = array();
                     foreach ($request as $key => $value) {
                         if (substr($key, 0, 3) == 'arg') {
                             $key = str_replace('arg', '', $key);
-                            $calling_args[$key] = $value;
+                            $anon_args[$key] = $value;
                             if (($index = array_search($key, $missing_args)) !== false) {
                                 unset($missing_args[$index]);
                             }
                         }
                     }

+                    // re-key the anon_args to be zero-based, and add in any values already set in calling_args (optional defaults)
+                    ksort($anon_args);
+                    $calling_args = array_values($anon_args) + $calling_args;
+
                     // Sort arguments by key -- @see ZF-2279
                     ksort($calling_args);

trunk-correct.diff

Index: tests/Zend/Rest/ServerTest.php
===================================================================
--- tests/Zend/Rest/ServerTest.php  (revision 21404)
+++ tests/Zend/Rest/ServerTest.php  (working copy)
@@ -542,9 +542,10 @@

     /**
      * @see ZF-1949
+     * @see ZF-9374
      * @group ZF-1949
      */
-    public function testMissingArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    public function testMissingAnonArgumentsWithDefaultsShouldNotResultInFaultResponse()
     {
         $server = new Zend_Rest_Server();
         $server->setClass('Zend_Rest_Server_Test');
@@ -552,10 +553,38 @@
         $server->handle(array('method' => 'testFunc7', 'arg1' => "Davey"));
         $result = ob_get_clean();
         $this->assertContains('<status>success</status>', $result, var_export($result, 1));
-        $this->assertContains('<response>Hello today, How are you Davey</response>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
     }

     /**
+     * @see ZF-9374
+     */
+    public function testMissingZeroBasedAnonArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    {
+        $server = new Zend_Rest_Server();
+        $server->setClass('Zend_Rest_Server_Test');
+        ob_start();
+        $server->handle(array('method' => 'testFunc7', 'arg0' => "Davey"));
+        $result = ob_get_clean();
+        $this->assertContains('<status>success</status>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
+    }
+
+    /**
+     * @see ZF-9374
+     */
+    public function testMissingNamesArgumentsWithDefaultsShouldNotResultInFaultResponse()
+    {
+        $server = new Zend_Rest_Server();
+        $server->setClass('Zend_Rest_Server_Test');
+        ob_start();
+        $server->handle(array('method' => 'testFunc7', 'who' => "Davey"));
+        $result = ob_get_clean();
+        $this->assertContains('<status>success</status>', $result, var_export($result, 1));
+        $this->assertContains('<response>Hello Davey, How are you today</response>', $result, var_export($result, 1));
+    }
+
+    /**
      * @group ZF-3751
      */
     public function testCallingUnknownMethodDoesNotThrowUnknownButSpecificErrorExceptionMessage()
Index: library/Zend/Rest/Server.php
===================================================================
--- library/Zend/Rest/Server.php    (revision 21404)
+++ library/Zend/Rest/Server.php    (working copy)
@@ -189,28 +189,35 @@

                     $func_args = $this->_functions[$this->_method]->getParameters();

+                    // calling_args will be a zero-based array of the parameters
                     $calling_args = array();
                     $missing_args = array();
-                    foreach ($func_args as $arg) {
+                    foreach ($func_args as $i => $arg) {
                         if (isset($request[strtolower($arg->getName())])) {
-                            $calling_args[] = $request[strtolower($arg->getName())];
+                            $calling_args[$i] = $request[strtolower($arg->getName())];
                         } elseif ($arg->isOptional()) {
-                            $calling_args[] = $arg->getDefaultValue();
+                            $calling_args[$i] = $arg->getDefaultValue();
                         } else {
                             $missing_args[] = $arg->getName();
                         }
                     }

+                    // anon_args may be 1-based (per docs), or 0-based (per incorrect Zend_Rest_Client @see ZF-9373)
+                    $anon_args = array();
                     foreach ($request as $key => $value) {
                         if (substr($key, 0, 3) == 'arg') {
                             $key = str_replace('arg', '', $key);
-                            $calling_args[$key] = $value;
+                            $anon_args[$key] = $value;
                             if (($index = array_search($key, $missing_args)) !== false) {
                                 unset($missing_args[$index]);
                             }
                         }
                     }

+                    // re-key the anon_args to be zero-based, and add in any values already set in calling_args (optional defaults)
+                    ksort($anon_args);
+                    $calling_args = array_values($anon_args) + $calling_args;
+
                     // Sort arguments by key -- @see ZF-2279
                     ksort($calling_args);


@froschdesign froschdesign added this to the 1.12.10 milestone Jan 5, 2015
@froschdesign froschdesign self-assigned this Jan 5, 2015
anupdugar added a commit to anupdugar/zf1 that referenced this issue Feb 6, 2015
Zend Framework 1.12.10

- [1: isLast not working as expected in Zend&zendframework#95;Service&zendframework#95;Amazon&zendframework#95;SimpleDb&zendframework#95;Page](zendframework#1)
- [8: Zend&zendframework#95;Loader&zendframework#95;ClassMapAutoloader is not auto included when using Zend&zendframework#95;Loader&zendframework#95;AutoloaderFactory::factory](zendframework#8)
- [15: Zend&zendframework#95;Db&zendframework#95;Table&zendframework#95;Abstract::delete does not delete from dependent table](zendframework#15)
- [32: Zend&zendframework#95;Soap&zendframework#95;Client has no 'exceptions' flag.](zendframework#32)
- [62: Zend&zendframework#95;Validate&zendframework#95;EmailAddress-&gt;&zendframework#95;validateMXRecords() fails on Umlaut-Domains](zendframework#62)
- [187: Zend&zendframework#95;Rest&zendframework#95;Server does not properly handle optional parameters when anonymous (arg1, etc) parameters are passed in](zendframework#187)
- [322: Zend&zendframework#95;Validate&zendframework#95;Hostname: disallowed Unicode code point](zendframework#322)
- [324: SlideShare API change some tag names.](zendframework#324)
- [345: CallbackHandler throws warning if WeakRef-extension not installed](zendframework#345)
- [377: Zend&zendframework#95;Console&zendframework#95;Getopt: Missing required parameter consumes next option as its parameter value](zendframework#377)
- [400: PHPUnit contraints: use real class names to help classmap generators](zendframework#400)
- [426: Use relative filenames for &zendframework#95;validIdns for direct include in Zend&zendframework#95;Validate&zendframework#95;Hostname](zendframework#426)
- [434: Corrected type of property &zendframework#95;currentRoute](zendframework#434)
- [440: Zend&zendframework#95;Controller&zendframework#95;Dispatcher&zendframework#95;Abstract::&zendframework#95;formatName() inconsistent with Action name handling](zendframework#440)
- [441: Loosen regex to allow nested function calls in SQL](zendframework#441)
- [444: Update Zend&zendframework#95;Validate&zendframework#95;Hostname TLDs list to 2014102301 version](zendframework#444)
- [446: fix typo unkown -&gt; unknown](zendframework#446)
- [448: fix travis ci build for php 5.2](zendframework#448)
- [449: Zend&zendframework#95;Date doesn't create correct date when seconds are missing from 8601 format](zendframework#449)
- [452: &quot;fluent&quot;, not &quot;fluid&quot;](zendframework#452)
- [453: Zend&zendframework#95;Cache&zendframework#95;Backend&zendframework#95;Memcached looks at &quot;bytes&quot;, but Couchbase 1.x returns &quot;mem&zendframework#95;used&quot;](zendframework#453)
- [456: Documentation of Zend&zendframework#95;Feed&zendframework#95;Pubsubhubbub&zendframework#95;Model&zendframework#95;ModelAbstract](zendframework#456)
- [458: Fixed bug in quoteInto with $count parameter and question sign in $value](zendframework#458)
- [461: CDATA section for category elements in RSS feed](zendframework#461)
- [465: Zend&zendframework#95;Currency creates invalid cache ids for values with fractions](zendframework#465)
- [467: debug&zendframework#95;backtrace() called twice when only once needed ](zendframework#467)
- [468: Zend&zendframework#95;Validate&zendframework#95;Hostname improvements](zendframework#468)
- [469: &zendframework#91;Zend&zendframework#95;Validate&zendframework#92; Testcase for zendframework#322](zendframework#469)
- [471: End of life for PHPUnit installation using pear](zendframework#471)
- [475: Zend Json Server Exception is missing the method name](zendframework#475)
- [478: Create .gitattributes to mirror archive { } in composer.json](zendframework#478)
- [480: Virtual machine doesn't install initial packages](zendframework#480)
- [483: Update copyright to 2015](zendframework#483)
- [484: Adds content headers on POST request in Zend&zendframework#95;Controller&zendframework#95;Request&zendframework#95;HTTP](zendframework#484)
- [487: Allow overriding cache id and tag validation in Zend&zendframework#95;Cache](zendframework#487)
- [488: Zend&zendframework#95;Dojo&zendframework#95;View&zendframework#95;Helper&zendframework#95;Dojo&zendframework#95;Container setCdnVersion error...](zendframework#488)
- [490: Added more specific return documentation for Zend&zendframework#95;Navigation Pages](zendframework#490)

# gpg verification failed.

Conflicts:
	README.md
	library/Zend/Application/Resource/Frontcontroller.php
	library/Zend/Application/Resource/Translate.php
	library/Zend/Barcode/Object/ObjectAbstract.php
	library/Zend/Controller/Router/Rewrite.php
	library/Zend/Db/Select.php
	library/Zend/EventManager/Filter/FilterIterator.php
	library/Zend/EventManager/GlobalEventManager.php
	library/Zend/Gdata/HttpAdapterStreamingProxy.php
	library/Zend/Mime/Part.php
	library/Zend/Mobile/Push/Message/Abstract.php
	library/Zend/Rest/Server.php
	library/Zend/Service/Rackspace/Files.php
	library/Zend/Service/SlideShare.php
	library/Zend/Test/PHPUnit/ControllerTestCase.php
	library/Zend/Validate/Hostname.php
	library/Zend/Version.php
dgiotas pushed a commit to tripsta/zf1 that referenced this issue Jun 17, 2016
antonis179 pushed a commit to tripsta/zf1 that referenced this issue Jan 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants