htaccess int:tolower redirected many times - .htaccess

i have activate RewriteMap in Virtualhost with:
RewriteEngine On
RewriteMap lc int:tolower
... and after that in htacess have this role:
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule . ${lc:%{REQUEST_URI}} [R=301,L]
... but make me redirected many times and don't get my REQUEST_URI every time redirect me to /.
I don't have idea why don't get it (on my old hosting work fine) if anyone has an idea and can help? I will be very happy and thank you in advance!

There's nothing actually "wrong" with the rule itself, however, I suspect you have a conflict with other directives that internally rewrite the URL (that may occur later in the file). The REQUEST_URI server variable is modified when the URL is rewritten - so does not necessarily contain the originally requested URL on subsequent passes through the rewrite engine.
To ensure the rule is only processed on the initial request and not the rewritten request we can check against the REDIRECT_STATUS environment variable, which is empty on the initial request and set to (string)200 (as in 200 OK status) after the first successful rewrite.
For example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule [A-Z] ${lc:%{REQUEST_URI}} [R=301,L]
Your original condition that checked against REQUEST_URI is unnecessary since this same check can be performed more efficiently in the RewriteRule directive itself.
You should also ensure that this rule is near the top of your .htaccess file, before any existing rewrites, since we still use REQUEST_URI in the substitution string.
You will need to ensure your browser cache is clear before testing and test first with a 302 (temporary) redirect to avoid potential caching issues.

Related

Redirect all URLS to new URL EXCEPT for /backend/ with .htaccess

I want to redirect all incoming queries to a new domain, except for /backend
I have this in my .htaccess, everything works, except for the /backend. I tried a few combinations, it just doesnt work.
I fear /backend is a virtual address....
what can i do?
HERE IS THE CODE:
RewriteCond %{HTTP_HOST} ^example.de$ [OR]
RewriteCond %{HTTP_HOST} ^www.example.de$
RewriteCond %{REQUEST_URI} !^/backend/$
RewriteRule (.*)$ https://www.bing.de/ [R=302,L]
PLEASE HELP. Thank you. Patrick
I fear /backend is a virtual address....
In which case you most probably have other mod_rewrite directives that rewrite the request to a front-controller (such as index.php) - and that's the problem. Whilst your existing rule includes an exception for /backend/ (the originally requested URL), so the rule is skipped on the first pass by the rewrite engine, once the request is rewritten to the front-controller (eg. index.php) the rewrite engine begins a 2nd pass which results in the rule being successfully executed since the URL is now /index.php (or whatever your front-controller is) and not /backend/.
You either need to:
modify the other directives that rewrite the request to the front-controller, so as not to trigger a 2nd pass through the rewrite engine. (You've not included your complete .htaccess file, so I'll discount this approach for now.)
OR, make sure you only examine the originally requested URL and not the rewritten URL. (The REQUEST_URI server variable is modified as the request is rewritten.)
However, I would assume that your /backend/ page also links to static assets (such as images, CSS, JS)? In which case, you also need to make exceptions for any additional static assets that are used by the page, otherwise these will also be redirected. For the sake of this example, I will assume all you static assets are located in an /assets subdirectory.
Try the following instead, near the top of your root .htaccess file:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.de [NC]
RewriteCond %{THE_REQUEST} !\s/backend/\s
RewriteRule !^assets/ https://www.bing.de/ [R=302,L]
Note that this rule must go before the rewrite to the front-controller.
The THE_REQUEST server variable contains the first line of the HTTP request headers and importantly, does not change as the request is rewritten. This contains a string of the form GET /backend/ HTTP/1.1 (containing the request method, URL and protocol).
If there are no external assets then change the RewriteRule pattern from !^assets/ to simply ^, to match everything.

htaccess block original file however allow rewrite

I have the following entries in my /.htaccess
RewriteEngine On
RewriteBase /
RewriteRule ^signin.php - [L,gone]
RewriteRule ^sign-in/?$ /signin.php [L]
What I am trying to achieve is to allow the user to access /sign-in but not the original file /signin.php
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
Thanks for any help.
To redirect any direct requests for /signin.php to /sign-in and internally rewrite /sign-in back to /signin.php then you can do it like this:
RewriteEngine On
RewriteRule ^signin\.php$ /sign-in [R=301,L]
RewriteRule ^sign-in$ signin.php [END]
The END flag (Apache 2.4) prevents any further loops by the rewrite engine, so prevents the rewritten URL being redirected back to /sign-in, which would otherwise cause a redirect loop.
The END flag is not required on the first rule, since an external redirect will trigger immediately. (The L flag is still required.)
You do not need the RewriteBase directive here.
I removed the optional trailing slash on /sign-in as this potentially creates a duplicate content issue. If you wish to allow an optional trailing slash then redirect to the canonical URL (without the trailing slash, or with if you prefer) instead.
UPDATE:
I saw this other question however when I tried to implement the answer I get gone error on both /sign-in and /signin.php.
Referenced Question:
Alias within htaccess, and block access to original file? (URL rewriting)
The Apache solution in the referenced answer is not quite correct. The answer would seem to have been "accepted" for the first part regarding doing this in PHP instead.
At the time of that question (2011), they would have been using Apache 2.2. The END flag was only introduced in Apache 2.4.
They would have needed to have done it like this, to prevent a redirect loop:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^about.php /about [L,R=301]
RewriteRule ^about$ about.php [L]

HTACCESS: Rewrite a Previously Rewritten URL Causes Error

not sure what my problem is, but I insert one rewrite into my htaccess file and the whole thing breaks. I used an htaccess tester and it says the rule works fine.
For some reason Google indexed the php file that I normally rewrite URLs to. So I need to take the .php page that displays and send it to the proper rewritten URL.
Here is the rule:
RewriteRule ^products/Automotive-Transmission-Torque-Converters-results.php$ /Search-Results [QSA,R=301,L]
The only thing I can think that would be causing the problem, is that I use this URL in another rewrite later on in my code.
Here is the second rewrite later on in the file:
RewriteRule ^Search-Results/?$ /products/Automotive-Transmission-Torque-Converters-results.php [QSA]
I hope I've identified the problem correctly. But again, I put the first rewrite rule into my htaccess and the the regular page doesn't show, the browser says there is an error on the page. Yet, htaccess testers say the rule works fine. Hence my suspicion.
RewriteRule ^products/Automotive-Transmission-Torque-Converters-results.php$ /Search-Results [QSA,R=301,L]
RewriteRule ^Search-Results/?$ /products/Automotive-Transmission-Torque-Converters-results.php [QSA]
Yes, these two directives used together will result in a redirect-loop (something that online testers don't appear to check for). The problem is that the first rule will trigger an external redirect after the second rule has rewritten the URL (when the rewrite engine starts over - in .htaccess).
The solution is to make sure the first rule (the external redirect) only triggers on direct requests from the client and not requests that have been internally rewritten.
We can check for direct HTTP requests by checking against the REDIRECT_STATUS environment variable, which is empty on the initial request and set to "200" (as in 200 OK HTTP status) after the first successful rewrite.
For example:
# Redirect direct request for PHP file to canonical URL
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^products/Automotive-Transmission-Torque-Converters-results\.php$ /Search-Results [R=301,L]
# Internally rewrite the canonical URL
RewriteRule ^Search-Results/?$ /products/Automotive-Transmission-Torque-Converters-results.php [L]
Note that I have removed the QSA from both rules, since it's not required here (the query string is appended by default). And I've included the L flag on the second rule. Also, don't forget to backslash escape the literal dot in the RewriteRule pattern.
Test first with 302 (temporary) redirect to avoid potential caching issues and make sure your browser cached is cleared before testing.
For some reason Google indexed the php file that I normally rewrite URLs to.
However, you need to try and identify how Google managed to find the PHP file/URL in the first place. If this is the a result of an incorrect internal link on your site then it needs to be fixed.

trouble with simple mod_rewrite redirect rule

I have mod_rewrite working in a development environment.
This testing domain is using these rules in an .htaccess file:
Options +FollowSymLinks
Options +Indexes
RewriteEngine on
# deal with potential pre-rewrite spidered / bookmarked urls
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
# deal with actual urls
RewriteRule ^clothes/[0-9a-z-]+-pr([0-9]+).php$ /clothes/product.php?pid=$1 [L]
The 2nd Rule works fine. Entering http ://testdomain.dev/clothes/shirt-pr32.php is silently delivered content from http ://testdomain.dev/clothes/product.php?pid=32 ...which is as desired and expected!
However, assuming this was applied to a live site, one that had originally used paths such as: http ://testdomain.dev/clothes/product.php?pid=32, I'd like to redirect any incoming requests following the old pattern to the new urls ...which is what the 1st Rule was intended to do.
My problem is my testing server seems to ignore the 1st Rule and serves the page as requested (page loads but address bar remains at http ://testdomain.dev/clothes/product.php?pid=32)
Any assistance or enlightenment would be most graciously accepted!
You need to match the query string within a RewriteCond, then backreference that RewriteCond from the rule. The RewriteRule only matches against the path, not the query string.
Here's a related post I previously answered with a similar request: Mod_rewrite rewrite example.com/page.php?v1=abc&v2=def to example.com/abc/def
You can't match against the query string in a rewrite rule, you need to use the `%{QUERY_STRING} variable in a condition and use the % to backrefernce groupings. So instead of:
RewriteRule ^clothes/index.php?pg=([0-9]+)$ /clothes/index$1.php [R=301,L]
You'll need:
RewriteCond %{QUERY_STRING} ^pg=([0-9]+)
RewriteRule ^clothes/index.php$ /clothes/index%1.php? [R=301,L]

Force removal of index.php with .htaccess

I'm currently using the following to rewrite http://www.site.com/index.php/test/ to also work directly with http://www.site.com/test/, but I would like to not only allow the second version, I would like to FORCE the second version. If a user goes to http://www.site.com/index.php/test/ it should immediately reroute them to http://www.site.com/test/. index.php should never appear in a url. Stipulation: this should only apply to the first index.php. If I have a title like http://www.site.com/index.php/2011/06/08/remove-index.php-from-urls/ it should leave the second index.php, as it is part of the URL.
Current rule that allows but does not force:
#Remove index.php
RewriteCond $1 !^(index.php|images|css|js|robots.txt)
RewriteRule ^(.*)$ /index.php/$1 [L]
Thanks.
As you wrote, if a user goes to http://www.site.com/index.php/test/ this rule will imediately reroute him to http://www.site.com/test/
RedirectMatch 301 /index.php/(.*)/$ /$1
I'm not sure if that is what you need as your current rewrite rule is opposite to mine.
First (and wrong) answer - see below
You can accomplish a redirection with these directives (in this order):
RewriteCond %{REQUEST_URI} ^index.php
RewriteRule ^index\.php/(.+)$ /$1 [R,L]
RewriteCond $1 !^(index.php|images|css|js|robots.txt)
RewriteRule ^(.*?)$ /index.php/$1 [L]
That will first redirect all the requests that begin with index.php to the corresponding shortened url, then silently serve index.php/etc with the second rule.
EDIT - Please read on!
In fact, the solution above generates an infinite redirection loop, because Apache takes the following actions (let's say we request /index.php/abc):
first RewriteCond matches
Apache redirects [R], that is, generates a new HTTP request, to /abc
/abc fails first RewriteCond
/abc matches second RewriteCond
Apache does not redirect, but rewrites this URI (so it makes an "hidden" request), to /index.php/abc . We are again at point 1, that's a loop.
Please note...
By using the [L] (last rule) flag, we can only tell Apache not to process more rewrite rules, but only if the current rule matches. Since a new HTTP request is made, there is no information about how may redirection we have been through yet. So, any time one of the two matches, and in any case it generates a new request (=>loop)
Using the [C] (chain rules) flag is kinda pointless because it makes Apache process a rule only if the previous rule matches, while the two rules we have are mutually excluding.
Using the [NS] (not if subrequest) flag on rule #1 is again not an option because it aƬsimply does not apply to our case (see Apache RewriteRule docs about it)
Setting env variables is not an option (alas), since a new request is made at pt 2, thus destroying all environment variables we set.
An alternative solution can be to rewrite e.g. /abc , to /index.php?path=abc. That is done by these rules (please, delete your RedirectMatch similar rule before adding these):
RedirectMatch ^/index\.php(/.*) $1
RewriteCond %{REQUEST_URI} !^/(index.php|images|css|js|robots.txt|favicon.ico)
RewriteRule ^(.+) /index.php?path=$1 [L,QSA]
I don't know the internals of CodeIgniter's scripts, but as most of the MVC scripts, it will read $_REQUEST['PATH_INFO'] to understand which page is requested. You could slightly modify the code that recognizes the page like this (I assumed that the page path is stored in the $page var):
$page = $_REQUEST['PATH_INFO'];
if(isset($_GET['path']) && strlen($_GET['path'])) $page = $_GET['path']; // Add this line
This won't break the previous code and accomplish what you asked for.

Resources