.htaccess satisfying rewrite rules in wrong order - .htaccess

I am trying to rewrite any blog posts my old forum to the new dedicated subdomain.
Old links are http://www.suzukiclubuk.co.uk/forum/viewtopic.php?p=113363 (topic id changes) and I am rewriting to be http://forum.suzukiclubuk.co.uk/viewtopic.php?p=113363
When testing with https://htaccess.madewithlove.be/ it rewrites correctly
RewriteCond %{HTTP_HOST} ^(www\.)?suzukiclubuk\.co.uk$
RewriteRule ^forum1/(.*)$ http://forum.suzukiclubuk.co.uk/$1 [L,R=301]
However when I test using the full .htaccess file it is satisfying the following prewritten joomla rules:
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule .* index.php [F]
I am to understand rules are applied from the bottom up and my rewrite rules are at the very bottom.
The question is how do I get my rule to be applied first before any other?

Related

Removing id/variable from SEO friendly URL

I am trying to rewrite a URL so that it is SEO friendly and excludes the product ID. Currently I am using this in my .htaccess file:
RewriteRule ^shop/product/([^/\.]+)/([^/\.]+)$ products.php?id=$2&name=$1 [NC,L]
For example rewrites it to:
shop/product/product-name/12
Is there a way that I can rewrite this URL so it removes or excludes the product ID from the end?
Could you please try following, written and tested with shown samples. Please make sure you clear your browser cache before testing your URLs.
First set of Rules is considering that your product.php is present in root, in same path as .htaccess is present.
RewriteEngine ON
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^shop/product/([^/]*)/([^/]*)/?$ /products.php?id=$2&name=$1 [NE,R=301,NC]
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{THE_REQUEST} \s/products\.php\?id=[^&]*&name=[^\s]*\s [NC]
RewriteRule ^(.*)$ shop/product [R=301,QSD,NE,L]
OR Please use either above OR following rules at a time only in your .htaccess.
RewriteEngine ON
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^shop/product/([^/]*)/([^/]*)/?$ products.php?id=$2&name=$1 [NE,R=301,NC]
RewriteCond %{QUERY_STRING} !^$
RewriteCond %{THE_REQUEST} products\.php\?id=[^&]*&name=[^\s]*\s [NC]
RewriteRule ^(.*)$ shop/product [R=301,QSD,NE,L]

htaccess mutliple rewrite rules for multiple domains

I have multiple urls and want to redirect old urls to their new ones.
The code below does work, so for example htaccess is catching www.domain-a.com/index.php?id=41 and redirects it with a 301 status code to the same domain with the path www.domain-a.com/our-conditions:
#301 redirect for domain A on a special id.
RewriteCond %{HTTP_HOST} ^www\.domain-a\.com$
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteCond %{QUERY_STRING} ^id=41(.*)$
RewriteRule .* https://%{HTTP_HOST}/our-conditions? [R=301,L]
#410 on for domain A on a special id.
RewriteCond %{HTTP_HOST} ^www\.domain-a\.com$
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteCond %{QUERY_STRING} ^id=52(.*)$
RewriteRule .* - [R=410,L]
#301 redirect for domain B on a special id.
RewriteCond %{HTTP_HOST} ^www\.domain-b\.com$
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteCond %{QUERY_STRING} ^id=221(.*)$
RewriteRule .* https://%{HTTP_HOST}/press? [R=301,L]
As you can see above that's a lot of code for just a few rules.
Now I thought that can be done better and I tried something different.
My idea was to have multiple RewriteRules for one domain. Usually that works just fine like this example here:
RewriteCond %{HTTP_HOST} ^www\.domain-a\.com$
RewriteRule ^press/material/(/?)$ https://%{HTTP_HOST}/press [R=301,L]
RewriteRule ^about/(/?)$ https://www.domain-b.de/impress [R=301,L]
Now i came up with this tryout:
#Multiple rules for domain A on a special id.
RewriteCond %{HTTP_HOST} ^www\.domain-a\.com$
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteRule ^index.php?id=41(/?)$ https://%{HTTP_HOST}/our-conditions? [R=301,L]
RewriteRule ^index.php?id=52(/?)$ - [R=410,L]
#Multiple rules for domain B on a special id.
RewriteCond %{HTTP_HOST} ^www\.domain-b\.com$
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteRule ^index.php?id=221(/?)$ https://%{HTTP_HOST}/press? [R=301,L]
The problem here is that my conditions do not apply. For example index.php?id=41 is just going trough htaccess and my application does say 404 (not found).
Can you help me out here to get my approach working?

Redirect `www` to `non-www` EXCEPT if its LetsEncrypt verification

I am trying to make the LetsEncrypt autoSSL crawler to work on my htaccess which is implementing whitelist method.
The crawler can successfully verify my domain as it can access:
$ curl -i http://example.com/.well-known/acme-challenge/BEKT19DL9JIG9S5GPP50XAL9ZSPAV54J
HTTP/1.1 200 OK
because my implementation of: (1)
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} ^\/[A-F0-9]{32}.txt(?:\ Comodo\ DCV)?$ [OR]
RewriteCond %{REQUEST_URI} ^\/[0-9]+\..+\.cpaneldcv$ [OR]
RewriteCond %{REQUEST_URI} /\.well\-known\/acme\-challenge
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule (.*) - [L]
</IfModule>
I have this rule to redirect www site version to non-www version: (2)
# Rewrite "www.example.com -> example.com"
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
So, to handle the crawler trying to verify the www of the domain and not getting the 301 redirect, I Implemented the following htaccess rule: (3)
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteCond %{REQUEST_URI} ^\/[A-F0-9]{32}.txt(?:\ Comodo\ DCV)?$ [OR]
RewriteCond %{REQUEST_URI} ^\/[0-9]+\..+\.cpaneldcv$ [OR]
RewriteCond %{REQUEST_URI} /\.well\-known\/acme\-challenge
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule (.*) - [L]
</IfModule>
BUT, the crawler is getting 301 permanent redirect when trying to verify the www version
$ curl -i http://www.example.com/.well-known/acme-challenge/BEKT19DL9JIG9S5GPP50XAL9ZSPAV54J
HTTP/1.1 301 Moved Permanently
I do not understand why the (2) htaccess rule is still causing the crawler to get 301 redirect, is there something wrong with my (3) rule?
To summarise, my problem is:
allow access to hidden directory: /.well-known/acme-challenge/ (only if it is an existing file)
if accessing it via the www version, don't redirect and serve the file (making the HTTP/1.1 status code 200)
Hope somebody can help.
Regards,
I am still not sure what is happening, but it appears rule (1) and (3) are the same RewriteRule with one differing RewriteCond, that does not seem to actually rewrite anything in the end. I am also not sure the exact behavior of using multiple checks in the same htaccess file.
At this point the easiest troubleshooting would be to simplify your rewrite rules to help identify what is happening.
Without actually testing, my simplified rewrite rules might look like this (I also cleaned up some backslashes that I did not think needed to be there, I could be wrong though):
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteCond %{REQUEST_URI} ^/[A-F0-9]{32}.txt(?:\ Comodo\ DCV)?$ [OR]
RewriteCond %{REQUEST_URI} ^/[0-9]+\..+\.cpaneldcv$ [OR]
RewriteCond %{REQUEST_URI} ^/\.well-known\/acme-challenge
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^.*$ - [L]
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
Again, without testing I read this as: All request patterns should match both rules, but the rules each have the LAST flag so processing should stop when one matches. In the rule without any rewriting, if %{HTTP_HOST} starts with www, and one of the three links is present (using OR flag instead of implicit AND) and is an existing file, do not rewrite and stop processing rewrite rules. If the request does not match any of those conditions, then the second RewriteRule will be processed, if %{HTTP_HOST} starts with www and the connection is not HTTPS, then rewrite to http://%1%{REQUEST_URI} using a 301 redirect and stop processing rewrite rules.
If none of that works and you still cannot figure what Apache is doing, it would be time to enable the RewriteRule debug logs (instructions would be different depending on which version of Apache you are using).

How to redirect from non-www to www with correct page?

I am trying to 301-redirect example.com to www.example.com by .htaccess:
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]
Problem: my-site.com/contact.html redirects to www.example.com/index.php instead of www.example.com/contact.html.
How can I accomplish that?
UPDATE: this is the complete .htaccess for my Joomla-site (comments stripped):
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule .* index.php [F]
###### this is the code in question...
RewriteCond %{HTTP_HOST} ^example$ [NC]
RewriteRule ^(.*)$ http://www.example/$1 [R=301,L]
# RewriteBase /
## Begin - Joomla! core SEF Section.
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} /component/|(/[^.]*|\.(php|html?|feed|pdf|vcf|raw))$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
# take care of sitemap.xml
RewriteCond %{REQUEST_URI} ^/sitemap.xml
RewriteRule .* /index.php?option=com_xmap&view=xml&tmpl=component&id=1&format=html [L]
I moved my two lines up just below RewriteEnigine On - but had the same problem again. Clueless.
Problem: example.com/contact.html redirects to www.example.com/index.php instead of www.example.com/contact.html.
I'm going to guess that you have other rules in your htaccess file, one that routes everything to index.php. You need to make sure that your redirect rule is before any other rule that you have.
After checking your htaccess file, you need to add an L flag at the end of your first rule:
RewriteRule .* index.php [F,L]
Because without it, the redirect gets applied even if the first rule gets applied (e.g. it gets rewritten to index.php with a 403 response waiting in the queue).
Firstly uncomment line
# RewriteBase / //Remove #
Below the above line write this code
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
I guess I'm already in the wrong for asking for clarification but you can just delete this.
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
I see you added an exclamation point and I've seen this redirect elsewhere without it. What does the exclamation point do in this case or is that incorrect?
Have a great day.

.htaccess Rewrite URL with a query string

I have tried a ton of solutions posted at stackoverflow but nothing seems to work for me. I would like to rewrite a few URLs on my site to be search engine friendly.
I would like a URL like this:-
http://www.mysite.com/index.php?filter=accounts
To display as:-
http://www.mysite.com/accounts
A lot of posts around the web give this as the solution:-
RewriteRule ^([^/]+)/?$ index.php?filter=$1 [QSA,L]
But this doesn't do anything.
My site is a Joomla CMS site and there are already some rewrites within the .htaccess file. Could it be that I am putting my new RewriteRule is the wrong place?
Here is the full .htaccess file without my new RewriteRule added
Options +FollowSymLinks
RewriteEngine On
# prevents people from accessing anything with phpMyAdmin
RewriteRule phpMyAdmin - [F]
# force canonical www if request is for non-www or has port number etc
RewriteCond %{HTTP_HOST} !^(www\.mysite\.com)?$
RewriteRule (.*) http://www.mysite.com/$1 [R=301,L]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
RewriteRule .* index.php [F]
RewriteBase /
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteCond %{REQUEST_URI} (/[^.]*|\.(php|html?|feed|pdf|raw))$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L]
Any help would be much appreciated.
:-)
UPDATED
Now is tested. Try this:
RewriteEngine On
RewriteRule ^([a-zA-Z0-9-=_?]+)/?$ index.php?filter=$1 [L]
.htaccess goes in root directory.
The requested URL is http://www.mysite.com/accounts/ but could be anything: http://www.mysite.com/apples/.
NOTE: The URL displayed in the address bar is the one that was entered in that address bar. I assume is not http://www.mysite.com/index.php?filter=accounts because I guess the purpose of the redirection is to replace it with a more friendly one (http://www.mysite.com/accounts), which is the one that has to be typed in the address bar, not the other way around. Little confusing but I hope it makes sense.
To test it, include the following only code at index.php in root directory.
<?php
if ($_GET['filter'] == 'accounts') {
echo "This is Accounts<br /><br />";
}else {
echo "This is INDEX<br /><br />";
}
?>
As to where to place the rewrite rules inside .htaccess, I could not know. I guess you have to try it before and after the actual rules.

Resources