Issues

ZF-4669: Zend_Controller_Request_Http->setPathInfo doesn't handle baseURL values correctly

Description

Reply to comment:

The fact that $routeTwo doesn't look correct is exactly the issue. I'm passing in the baseURL ('/app') in my case which is how the current code knows the strip the first four characters (strlen('/app') = 4.) The problem that is it's possible for the router to encounter URLs which do not have the correct baseURL value and therefore they shouldn't have their initial characters stripped. The use case is when one would like to build a "routing" controller which transposed (legacy in my case) URLs (completely arbitrary) to MVC-formatted URLs (baseUrl/module/controller/action/.) One can do this today, using a legacy URL routing approach per $routeTwo, but it's odd and non-obvious...

My proposal is to use a regex to determine if the initial characters of the URL match the provided $baseURL before stripping the initial characters of the request URI and to not modify the request URI if they do not match.

P.s. I gave the ``` thing a try but it doesn't seem to like my syntax for some reason. Sorry...

Initial report:

If you have a baseURL set, setPathInfo's implementation strips the length of the baseURL from the request URI, not the baseURL's value itself. This makes it difficult to setup Zend_Controller_Router_Route_* rules to route from legacy URL(s) to Zend Framework MVC+mod_rewrite URL(s). Example:

$router = new Zend_Controller_Router_Rewrite(); $routeOne = new Zend_Controller_Router_Route_Static( '/directory/index.php', array( 'module' => 'someModule', 'controller' => 'someController', 'action' => 'someAction' ) ); $routeTwo = new Zend_Controller_Router_Route_Static( 'ectory/index.php', array( 'module' => 'someModule', 'controller' => 'someController', 'action' => 'someAction' ) ); $router->addRoutes(array($routeOne , $routeTwo ));

$frontController->setControllerDirectory(array('default' => '../application/default/controllers', 'api' => '../application/api/controllers')) ->setRouter($router) ->setBaseUrl('/app');

RouteTwo "matches" but RouteOne does not. Because the first four characters are missing (strlen('/app')) there are potential issues with naming overlap.

Suggested fix, replace:

Zend/Controller/Request/Http.php:551 if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl)))))

with

Zend/Controller/Request/Http.php:551 if ((null !== $baseUrl) && (false === ($pathInfo = preg_replace("/^".$baseUrl."/", "", $requestUri))))

This will cause the baseURL to be stripped for requestURI's which have it, but not alter requestURI's which don't - allowing a developer to handle that case with their own routing.

Comments

I think part of your code was stripped on submission, as the route indicated in $routeTwo does not look correct. (Use ``` to enter code)

Looking at your "solution", the only difference I see is that it appends an additional '/' to the $baseUrl when stripping it. Have you tried changing the baseUrl you pass to the front controller to include the trailing '/'?

Please add more information on how to property reproduce and reopen.

Thanks, Ralph