Issues

ZF-6976: Zend_Controller_Router_Route_Chain doesn't reset pathInfo in request

Issue Type: Bug Created: 2009-06-10T07:50:14.000+0000 Last Updated: 2012-01-19T15:07:20.000+0000 Status: Open Fix version(s): Reporter: Edward Surov (zooh) Assignee: Matthew Weier O'Phinney (matthew) Tags: - Zend_Controller

Related issues: Attachments: - Chain.patch

Description

Let's suppose we're trying to match the following URL: /part1/part2/part3a And we have the following chains: part1->part2->part3a part1->part2->part3b

Last chain tries to match our URL and fails on the last part. Then first chain tries to match... but not the whole URL, because $request->getPathInfo() returns only part3a now! The solution is to call $request->setPathInfo($path) before returning false from inside the foreach() that iterates the routes, not only after finishing the foreach().

P.S.: I tried to avoid patching the ZF source by extending Zend_Controller_Router_Route_Chain with my custom class, but Zend_Controller_Router_Route_Abstract cannot be tuned to use my class in chain() method - it's hardcoded there.

Comments

Posted by Edward Surov (zooh) on 2009-11-23T15:29:13.000+0000

Important notice: this bug occurs only if part3b route's getVersion() returns 2 or greater.

Posted by Edward Surov (zooh) on 2009-11-23T16:21:19.000+0000

This patch solves the problem.

Posted by Peter Moolenaar (petermoolenaar) on 2010-06-01T06:19:21.000+0000

I'm having the same issue... It affects (at least) version 1.10

Although this patch does fix the problem related to the Chain route, the problem might be more related to modifying the Request_Http object. Actually changing the Request_Http object to pass along some modifications seems to be a bit misplaced or am I missing something important??

Using the actual request object in a route (version 2) seems feasible, but it might not be when dealing with chained routes. Any thoughts?

Posted by Martin Minka (k2s) on 2012-01-19T15:07:20.000+0000

The provided patch solves the problem. The chain class is calling $request->setPathInfo($path) in case that it finds match, but it doesn't do it when not (places where return false; is calles).

I am providing test where it is shown how evaluating route A is influencing route B evaluation.

Output of this test is:

<pre class="highlight">
1. test matches, path info=/xxx/too
B route matches: yes
2. test fails which is correct, path info=xxx/too
A route matches: no
3. test fails which is wrong, reason is that the route A has change path info=too
B route matches: no
finished.

Source:

<pre class="highlight">
require_once 'Zend/Controller/Router/Rewrite.php';
require_once 'Zend/Controller/Dispatcher/Standard.php';
require_once 'Zend/Controller/Router/Route/Chain.php';
require_once 'Zend/Controller/Router/Route.php';
require_once 'Zend/Controller/Router/Route/Module.php';
require_once 'Zend/Controller/Router/Route/Static.php';
require_once 'Zend/Controller/Router/Route/Regex.php';
require_once 'Zend/Controller/Router/Route/Hostname.php';


require_once 'Zend/Controller/Request/Http.php';

$prefixRoute = new Zend_Controller_Router_Route('/xxx/');

$_SERVER['HTTP_HOST'] = '<a href="www.test.com">www.test.com</a>';
$request = new Zend_Controller_Request_Http("http://<a href="www.test.com/xxx/too">www.test.com/xxx/too</a>");

$a = getRouteA($prefixRoute);
$b = getRouteB($prefixRoute);

echo "1. test matches, path info=".$request->getPathInfo().PHP_EOL;
echo "B route matches: ".($b->match($request) ? "yes" : "no").PHP_EOL;
echo "2. test fails which is correct, path info=".$request->getPathInfo().PHP_EOL;
echo "A route matches: ".($a->match($request) ? "yes" : "no").PHP_EOL;
echo "3. test fails which is wrong, reason is that the route A has change path info=".$request->getPathInfo().PHP_EOL;
echo "B route matches: ".($b->match($request) ? "yes" : "no").PHP_EOL;
die("finished.");

/*** helpers ***/
function getRouter()
{
    $router = new Zend_Controller_Router_Rewrite();
    $router->removeDefaultRoutes();
    return $router;
}

function getRouteA($prefixRoute)
{
    $chain = new Zend_Controller_Router_Route_Chain();
    $foo = new Zend_Controller_Router_Route_Hostname('<a href="www.zend.com">www.zend.com</a>', array('foo' => 1));
    $bar = new Zend_Controller_Router_Route_Static('bar', array('bar' => 2));
    $chain->chain($foo)->chain($bar);
    return $prefixRoute->chain($chain);
}

function getRouteB($prefixRoute)
{
    $too = new Zend_Controller_Router_Route_Static('too', array('ok' => 1));
    return $prefixRoute->chain($too);
}

Have you found an issue?

See the Overview section for more details.

Copyright

© 2006-2016 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.

Contacts