|
|
|
Ok, failed test are becouse DOCUMENT_ROOT is not set in tests. I'll look into this.
Could you test something for me, Laurent? Test if it works - change rewrite detection in RewriteRouter constructor to this:
$base = dirname(str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']));
$base = rtrim(str_replace('\\', '/', $base), '/'); // windows and unix dirname
$filename = basename($_SERVER['SCRIPT_FILENAME']);
if (strpos($_SERVER['REQUEST_URI'], $filename) !== false) {
$base .= '/' . $filename;
}
$this->_rewriteBase = rtrim($base, '/');
Checking for filename is there for testing if RewriteEngine is off (it may be replaced by different code). Of course 4-7 will still not work. I will givie it a try on my Windows machine in a couple of hours - on Apache and IIS. I have optimized it a bit:
$base = str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']); if (strpos($_SERVER['REQUEST_URI'], basename($_SERVER['SCRIPT_FILENAME'])) === false) { $base = str_replace('\\', '/', dirname($base)); // windows and unix dirname } $this->_rewriteBase = rtrim($base, '/'); http://instdev2.dev.fdj.fr/zf/ctl/action/
RB=/zf OK but Exception raised http://instdev2.dev.fdj.fr/zf/ctl/action/param http://instdev2.dev.fdj.fr/zf/ctl/action/param/index.php http://instdev2.dev.fdj.fr/zf/ctl/action/param?bingo http://instdev2.dev.fdj.fr/zf/ctl/action/param/index.php http://instdev2.dev.fdj.fr/zf/ctl/action?test=index.php http://instdev2.dev.fdj.fr/zf/ctl/action/index.phpold http://instdev2.dev.fdj.fr/zf/ctl/action/rolindex.php Forget exception... It come from a type in url test.
May I ask for another test?
$base = str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']); if (!strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])) // for Apache config rewrite || strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === false) { $base = str_replace('\\', '/', dirname($base)); // windows and unix dirname } $this->_rewriteBase = rtrim($base, '/'); Following url still have RB set to /zf/index.php and then are misrouting to Index Controller instead of ctl Controleur
http://instdev2.dev.fdj.fr/zf/ctl/action/param/index.php Where do you keep your RewriteRule directive? I know you said you have tested it in .htaccess and config files but I mean where you have kept it while testing the above code? I'll try to reproduce.
The problem is when you place RewriteRule in <VirtualHost> because $_SERVER['SCRIPT_NAME'] is initialized incorrectly. But when you use it in .htaccess or <Directory> all is well. Could you confirm it? And hopefully last code modification:
$base = str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']); if (isset($_SERVER['SCRIPT_URL']) // for Apache config <VirtualHost> rewrite compatibility || strpos($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']) === false) { $base = str_replace('\\', '/', dirname($base)); // windows and unix dirname } $this->_rewriteBase = rtrim($base, '/'); Indeed, i did my first tests on both .htaccess and httpd.conf with a virtual host.
But, after, i was testing only in virtual host wich is my production configuration... I did test again on both.. I dont have time to finish this comment that you posted some new code... Nice job Please leave it open, I still have to commit it to svn. But first I have to test it on different setups.
what did you do with detectRewriteBase() ?
public function detectRewriteBase() { $base = ''; if (!isset($_SERVER['PATH_INFO'])) $base = $_SERVER['REQUEST_URI']; else if ($pos = strpos($_SERVER['REQUEST_URI'], $_SERVER['PATH_INFO'])) { $base = substr($_SERVER['REQUEST_URI'], 0, $pos); }; return rtrim($base, '/'); } this line is terrible, now rewrite base alway equals to REQUEST_URI if (!isset($_SERVER['PATH_INFO'])) $base = $_SERVER['REQUEST_URI'];
If there is no PATH_INFO then you're at root application directory (on index.php) and then Request URI is your rewrite base.
If you're not on your root, then you've hit a bug - try moving RewriteRule from <VirtualHost> to <Directory> or .htaccess. Michael Minicki, you are not right, $_SERVER['REQUEST_URI'] contains GET request string
detectRewriteBase() must be like this, it fixes the problem public function detectRewriteBase() { $base = ''; if (!isset($_SERVER['PATH_INFO'])) { $filename = basename($_SERVER['SCRIPT_FILENAME']); $base = $_SERVER['SCRIPT_NAME']; if (strpos($_SERVER['REQUEST_URI'], $filename) === false) { // Default of '' for cases when SCRIPT_NAME doesn't contain a filename (ZF-205) $base = (strpos($base, $filename) !== false) ? dirname($base) : ''; } } else if ($pos = strpos($_SERVER['REQUEST_URI'], $_SERVER['PATH_INFO'])) { $base = substr($_SERVER['REQUEST_URI'], 0, $pos); } return rtrim($base, '/\\'); } Of course it contains GET URI. And for URL of 'http://localhost/test/index.php/archive/2006/05' and 'http://localhost/test/archive/2006/05' request URI is set to '/test/index.php/archive/2006/05' or '/test/index.php/archive/2006/05' and path info SHOULD be set to '/archive/2006/05'. It's not empty and is just subtracted from request uri leaving '/test/index.php' or '/test' as rewrite base.
If you request application root - 'http://localhost/test/index.php' and 'http://localhost/test/' then path info is not present and your reqest URIs are your rewrite bases - '/test/index.php' and '/test/'. BUT! There is a bug (probably in php) which makes path_info unreliable on certain conditions. It doesn't get initialized when it should. See: http://bugs.php.net/bug.php?id=38141 And check if this is your case. PS. As I told you before - move your RewriteRules to htaccess and you'll see. I'm getting unexpected results, too! The method 'detectRewriteBase()' is always returning '/activities/ssc' from the address 'http://www.client.dev/activities/ssc'
This is the current $_SERVER values:- [SERVER_SOFTWARE] => Apache/2.2.0 (Fedora)
[SERVER_NAME] => www.client.dev
[SERVER_ADDR] => 10.0.1.250
[SERVER_PORT] => 80
[REMOTE_ADDR] => 10.0.1.250
[DOCUMENT_ROOT] => /home/aaa/bbb/www.client.dev/docs
[SERVER_ADMIN] => root@localhost
[SCRIPT_FILENAME] => /home/aaa/bbb/www.client.dev/docs/index.php
[REDIRECT_URL] => /activities/ssc
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.0
[REQUEST_METHOD] => GET
[QUERY_STRING] =>
[REQUEST_URI] => /activities/ssc
[SCRIPT_NAME] => /index.php
[PHP_SELF] => /index.php
[REQUEST_TIME] => 1154834871
The paths are set up as follows:- $router = new Zend_Controller_RewriteRouter(); $router->addRoute('activities', new Zend_Controller_Router_Route('activities/:action/:id/:sid', array('controller' => 'activities', 'action' => 'index', 'id' => 'index', 'sid' => ''), array('action' => '^\w+$', 'id' => '^\w+$', 'sid' => '^\w+$'))); $router->addRoute('training', new Zend_Controller_Router_Route('training/:id/:sid', array('controller' => 'training', 'action' => 'index', 'id' => 'index', 'sid' => ''), array('id' => '^\w+$', 'sid' => '^\w+$'))); $front = Zend_Controller_Front::getInstance(); $front->setRouter($router); $front->setControllerDirectory(PeptoCMS::path('app') . '/controllers'); $front->dispatch(); I've noticed a few ways of determing the auto base url from above but these seem to give inconsistent results. For example $_SERVER['DOCUMENT_ROOT'] will only be set on an Apache webserver, not IIS. What I can't understand is how useful this feature is - surely if you've set your rewriting for ANYTHING to resolve to /test/index.php and your URL is http://www.client.dev/test/my/test Sorry - forgot to add the patch
public function detectRewriteBase() { $base = ''; if (!empty($_SERVER['PATH_INFO'])) { if (($pos = strpos($_SERVER['REQUEST_URI'], $_SERVER['PATH_INFO'])) !== false) { $base = substr($_SERVER['REQUEST_URI'], 0, $pos); } } return rtrim($base, '/'); } Michael Minicki, it seems to be a problem with apache 1.3.x only (i have this one on my dev server). $_SERVER doesn't have PATH_INFO key in all cases. But, it has key ORIG_PATH_INFO.
Here is my situation: php runs as cgi .htaccess contents RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !\.(swf)|(jpg)|(png)|(gif)$
RewriteRule ^(.*) index.php5
DirectoryIndex index.php5
doc_root=/home/site/www/ bootstrap file in /home/site/www/somedir/index.php5 get request: http://site/somedir/aaa/bbb/ $_SERVER contents array(40) {
["DOCUMENT_ROOT"] => string(21) "w:/home/site/www"
["HTTP_HOST"] => string(9) "site"
["REDIRECT_REDIRECT_STATUS"] => string(3) "200"
["REDIRECT_STATUS"] => string(3) "200"
["REDIRECT_URL"] => string(15) "/somedir/index.php5"
["SCRIPT_FILENAME"] => string(36) "w:\home\site\www\somedir\index.php5"
["REQUEST_URI"] => string(18) "/somedir/aaa/bbb/"
["SCRIPT_NAME"] => string(15) "/somedir/index.php5"
["ORIG_PATH_TRANSLATED"] => string(36) "w:\home\site\www\somedir\index.php5"
["ORIG_PATH_INFO"] => string(15) "/somedir/index.php5"
["ORIG_SCRIPT_NAME"] => string(18) "/_php5/php-cgi.exe"
["ORIG_SCRIPT_FILENAME"] => string(27) "/usr/local/php5/php-cgi.exe"
["PHP_SELF"] => string(15) "/somedir/index.php5"
}
Simon, I'll comment your example. If you set your rewriting for ANYTHING to resolve to /test/index.php and your URL is http://www.client.dev/test/my/test
REQUEST_URI: /test/my/test I know it's not like that in your case but it's how it should be according to CGI specification. It's an Apache/PHP bug. Guys, move your rules please. If you have set them like that: <VirtualHost *:80>
ServerName test.intranet
DocumentRoot /var/www/test/htdocs
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
</VirtualHost>
Just set them this way: <VirtualHost *:80>
ServerName test.intranet
DocumentRoot /var/www/test/htdocs
<Directory /var/www/test/htdocs>
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
</Directory>
</VirtualHost>
It works with Apache 2 this way. If placed directly under VirtualHost you have a problem with variables initialized incorrectly. I would like to avoid hacking for avoiding other software bugs. If you insist on keeping your RewriteRules in the old place, then just use setRewriteBase for now. Set your bases accordingly - in your example, Simon, it should be set to '/test'. I am waiting for PHP and Apache devs to come up with a solution. If they won't resolve it quickly, I will contact Zend and ask for their decision. And for the inconsistent results and DOCUMENT_ROOT not set on IIS. That's why I want to stick only to vars available in CGI specification. They should be supported by any web server which complies with it.
Hi Martel - I'll give that a try and confirm that works.
However wouldn't the patch I provided still work in either case? If PATH_INFO is not set, don't apply the base_url. If it is, remove it from the REQUEST_URI and it resolves correctly. I don't have problems modifying my Apache configs, but perhaps there are some (albeit unlucky) users who are restricted by how much they can play with their config files. OK - Have just checked and (must have slipped my mind) but the Rewrite directives ARE already in the directory scope, not the virtualhost. Are the 'multiviews' likely to cause trouble with the PATH_INFO? AcceptPathInfo is not set in either the global nor virtualhost scope.
Here's the config for clarity: DocumentRoot "/home/aaa/bbb/www.client.dev/docs" ServerName www.client.dev ServerAdmin webmaster@peptolab.com DirectoryIndex index.php index.html <Directory "/home/aaa/bbb/www.client.dev/docs"> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] AllowOverride None Order allow,deny Allow from all </Directory> Simon, you can't ignore the rewrite base if path_info is empty. If you have a file of /test/index.php and a URL of http://localhost/test/
REQUEST_URI: '/test' So the rewrite base has to be '/test' and not '/'. The problem is, whichever approch to detect rewritebase you choose you hit some problems. The code I have proposed to Laurent won't work with CGI version of PHP for instance (I mean CGI under Apache). The current solution at least uses a standard and well documented variables. I think it would be best if you could provide some feedback on PHP and Apache bug trackers. If the devs see the problem touches more than one person they may be motivated better: http://bugs.php.net/bug.php?id=38141 I've just moved a site from a host that had mod_php to a one that runs it as FCGI, and have been hit by this issue. My routing was broken, and I don't even have a rewrite base because the site is in document root. The problem was that, instead of figuring out that rewrite base is an empty string, RewriteRouter thought rewrite base was the whole REQUEST_URI because of this line:
if (empty($_SERVER['PATH_INFO'])) $base = $_SERVER['REQUEST_URI']; Now, I don't quite understand the whole background and complexity of this problem in different environments, but it should be obvious that the primary goal of detectRewriteBase() should be positively detecting that there is no rewrite base when the site is in root. Detecting the rewrite base when there really is a prefix only comes in second. What good is automatic detection of base when the same feature breaks routing if site is in root? I recommend we move this issue completely out of the core ZF components. Instead, I suggest using an empty string as the default rewriteBase, if no default is given in the ZF global "INI" (proposal coming soon).
Then, I propose moving all code (also see The test should be interactive, such the the user immediately sees and corrects any problems. Thus, test results submitted back to our data collection process on the community server should have a reasonable degree of accuracy. Lastly, I suggest asking for volunteers to work together in creating the test script, data collection process, and work on analyzing the results and improving the test script. One alternative to consider:
Use Zend_Cache instead to seed the default value in the registry. If the rewriteBase has not been set, or the "signature" of the key $_SERVER variables has changed, then load the source code for calculating rewriteBase, make the calculation, and store the result to Zend_Cache. This would add Zend_Cache as a required component for many "Hello World!" programs using the rewriteRouter, adding weight to even the simplest of ZF applications. Another variation of the alternative above: Use a global Zend "INI" file for caching a small number of super simple auto-generated things, like a calculated rewriteBase, thus avoiding requiring Zend_Cache. Rewrite base detection (and handling) was recently moved to Request class (with a major rewrite to whole Controller module). At the time of writing modified code is evaluated in the incubator.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
First three should work while they don't on your configuration. What's your PHP version? What is your operating system and what is your webserver?
For 4-7 I will prepare a fix but let's resolve your problem first.