We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

IndexController cause unmanaged 404 error on Apache w mod_rewrite - hint for any new dev.

Hello guys, I don't know if this as been already talked or documented but i will post it to help any new phalcon user that encounter the same problem.

It's not a Phalcon bug or internal problem, but an enviroinment config problem. I think it should be included in documentation to avoid to loose time. The problem is simple and comes out if you :

  • are on Apache with mod_rewrite
  • have a controller named like IndexController (or something that match the default php file loaded by the server) (and is more evident if you:) have a Router config that automatically match controller/action in the url.

Problem: you could never request an url like "host/index/youraction" as mod_rewrite and actual default rewriting rules in the .htaccess provieded with Phalcon sample projects are broken for this case. It will result in a 404 error (not managed by Phalcon)

Explication of the problem: I'm pasting here the comment i've included in my BaseController to remind me what to not do

/**
* Pay attention to the name of the controller!
* It should never be "IndexController" or any name that match the DEFAULT php file loaded by the server (eg. index.php)
* because mod_rewrite catch and confuse the 'index' word in the url as filename
* and breaks all the rules stripping it from the url requested.
* eg. if we have
* $router-add("/:controller/:action", array(
* 'controller' = 1,
* 'action' = 2,
* ));
* and request the url <a href="https://host/index/test">https://host/index/test</a> to request the testAction in IndexController
* it wont work (causing a pure 404 error neither ever sent to the framework) as mod_rewrite will
* parse the url in subsequent internal redirect with this steps:
* 1) /public/index/test (as for the root .htaccess)
* 2) (public/)index.php/test (as for the public/ .htaccess) <--- PROBLEM!!
* as you can see the /index/ part of the requested url is stripped off the url between redirects as
* it is recognized as the default index.php file in the current dir
*(mod_rewrite log show "strip per-dir prefix" as the culprit transformation)
* this cause the RewriteCond in public/.htaccess to be matched (by mistake) as follow:
* pattern='!-d' = matched
* pattern='!-f' = not-matched <---- HERE THE CONSEGUENCE!!
* because it find index.php IS AN EXISTING FILE (as it is) and try execute it directly with wrong parameters
* instead of executing the next rewriting rule (that couldn't be executed as the last of the condition is NOT MATCHED).
* On the contrary, the default correct rewriting should transform and redirect the original url to
* public/index.php?_url=index/test
*
*/

My Workaround for now, before investigate more on a definitive solution on rewriting rules, is to rename the IndexController to something like "HomeController".

Hope this help.

Not sure but maybe you have MultiViews enabled in apache

Well, i'm on Debian with a default configuration on Apache... never added/touched Multiviews option. I've searched documentation about this option and it seems it is not set by default. Anyway also if it is set by default, it is good to be warned about.

Also i've done a little test on my server and i've proved it is not enabled. The test is the following:

  • created a test.php file with a simple "echo" in the root folder.
  • disabled/renamed any .htaccess (So also RewriteEngine is not set to ON)
  • requested host/test.php ->returned the simple echo string.
  • requested host/test and host/test/ -> both returned 404 error. So the Multiviews is no enabled.

As for the documentation, if multiviews was enabled, host/test should return me the simple echo string.



2.2k

@aledelgo

I can't read your explanation. There is something wrong with Markdown.

Would you please fix it?

Hi @kenjis,

i tried to edit the post to fix the format of the PHP code but i don't have any good result. In the edit textbox it seems well recognized php code (well formatted), but in the preview box it is displayed ugly as you can see here...

No idea of what i could do.



2.2k

I don't know why your post is ugly.

I get the php part from HTML, and decoded.

/**
* Pay attention to the name of the controller!
* It should never be "IndexController" or any name that match the DEFAULT php file loaded by the server (eg. index.php)
* because mod_rewrite catch and confuse the 'index' word in the url as filename
* and breaks all the rules stripping it from the url requested.
* eg. if we have
* $router-add("/:controller/:action", array(
* 'controller' = 1,
* 'action' = 2,
* ));
* and request the url <a href="https://host/index/test">https://host/index/test</a> to request the testAction in IndexController
* it wont work (causing a pure 404 error neither ever sent to the framework) as mod_rewrite will
* parse the url in subsequent internal redirect with this steps:
* 1) /public/index/test (as for the root .htaccess)
* 2) (public/)index.php/test (as for the public/ .htaccess) <--- PROBLEM!!
* as you can see the /index/ part of the requested url is stripped off the url between redirects as
* it is recognized as the default index.php file in the current dir
*(mod_rewrite log show "strip per-dir prefix" as the culprit transformation)
* this cause the RewriteCond in public/.htaccess to be matched (by mistake) as follow:
* pattern='!-d' = matched
* pattern='!-f' = not-matched <---- HERE THE CONSEGUENCE!!
* because it find index.php IS AN EXISTING FILE (as it is) and try execute it directly with wrong parameters
* instead of executing the next rewriting rule (that couldn't be executed as the last of the condition is NOT MATCHED).
* On the contrary, the default correct rewriting should transform and redirect the original url to
* public/index.php?_url=index/test
*
*/

Got it working re-pasting code prefix and suffix from the help page.

I don't know why your post is ugly.

I get the php part from HTML, and decoded.

/**
* Pay attention to the name of the controller!
* It should never be "IndexController" or any name that match the DEFAULT php file loaded by the server (eg. index.php)
* because mod_rewrite catch and confuse the 'index' word in the url as filename
* and breaks all the rules stripping it from the url requested.
* eg. if we have
* $router-add("/:controller/:action", array(
* 'controller' = 1,
* 'action' = 2,
* ));
* and request the url <a href="https://host/index/test">https://host/index/test</a> to request the testAction in IndexController
* it wont work (causing a pure 404 error neither ever sent to the framework) as mod_rewrite will
* parse the url in subsequent internal redirect with this steps:
* 1) /public/index/test (as for the root .htaccess)
* 2) (public/)index.php/test (as for the public/ .htaccess) <--- PROBLEM!!
* as you can see the /index/ part of the requested url is stripped off the url between redirects as
* it is recognized as the default index.php file in the current dir
*(mod_rewrite log show "strip per-dir prefix" as the culprit transformation)
* this cause the RewriteCond in public/.htaccess to be matched (by mistake) as follow:
* pattern='!-d' = matched
* pattern='!-f' = not-matched <---- HERE THE CONSEGUENCE!!
* because it find index.php IS AN EXISTING FILE (as it is) and try execute it directly with wrong parameters
* instead of executing the next rewriting rule (that couldn't be executed as the last of the condition is NOT MATCHED).
* On the contrary, the default correct rewriting should transform and redirect the original url to
* public/index.php?_url=index/test
*
*/

Instead of rewriting the IndexController to Home, etc., just disable multiviews in apache .htaccess file in the /public directory. I found this was a problem as well on my vagrant box so just adding Options -MultiViews to the invo .htaccess file did the trick. Great suggestion, Tomasz.

Not sure but maybe you have MultiViews enabled in apache



139
edited Aug '16

Thanks, It works for me as well!

just adding Options -MultiViews to the invo .htaccess

Instead of rewriting the IndexController to Home, etc., just disable multiviews in apache .htaccess file in the /public directory. I found this was a problem as well on my vagrant box so just adding Options -MultiViews to the invo .htaccess file did the trick. Great suggestion, Tomasz.

Not sure but maybe you have MultiViews enabled in apache