How to do everything at once in mod rewrite?

I write a website in PHP, I use the Apache server. I need to make a redirect from the www address, human-readable URLs, a redirect to the canonical URL, multilingualism, ban some user agents, ban users by IP, and much more with mod_rewrite, and that all this is configured through the admin panel.

How do I do this?

Author: Kyubey, 2016-07-08

2 answers

You're going the wrong way. If you do everything through mod_rewrite, then you will face a lot of problems:

  • You'll be mired in tons of unreadable and unsupported code. This language is not designed for complex logic, although it is conditionally complete by Turing.

  • You will nail your site to the Apache server. If you want to use nginx, you will have serious problems.

  • Debug the rules practically impossible. If you encounter a bug that is not fixed by looking closely at the code, then it will be difficult to find the error.

  • If you have editable rules via the admin panel (human-readable URLs, banned IP ranges, etc.), then programmatically editing .htaccess will be problematic.

In modern frameworks and CMS, routing through the front controller is widely used. Here's everything you need:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?_route=$1 [L,QSA]

Now in index.php you will have a path in $_GET['_route'], all other parameters in the GET request will also be saved. You can write whatever logic you want in a language that you know and understand well, using any means like accessing the config to get routing settings and accessing the database to get banned IP ranges.

If you don't mind accessing the path via $_SERVER['REQUEST_URI'] instead of $_GET['_route'], then you can simplify .htaccess even more, as indicated in the notes to the other answer:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L,QSA]

P. S. The canonical URL is usually it is enough to specify in the meta-information of the page. Redirects due to the absence of / at the end only waste resources. You can also use History.replaceState so that the URL in the browser's address bar is also canonical.

 36
Author: Kyubey, 2020-05-16 03:37:20

Based on the question: Why does it eat the slash in the bracket group of the regular expression?

If you use this redirection:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?_route=$1 [L,QSA]

Then when requesting the form

http://localhost//activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd//lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko

In the $_GET['_route'] variable, we get an incorrect result:

                  activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd/lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko

Double slash replaced with single slash!

I think that it is more correct to use this redirection:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteRule ^ index.php?_route=%1 [L,QSA]

Then in the variable $_GET['_route'] we get the result:

                 /activation-account/$2y$10$Xl40W/SKTOXYcxfCxGszr.9tbd//lNJSVJTpBh4umjWf/9GNMSlJy/loginfiko

Double slashes on place + the second slash after host got into the variable.

P.S. No one canceled the variable $_SERVER['REQUEST_URI'] the contents of which can be parsed as you like.

 13
Author: Visman, 2018-01-07 06:27:02