htaccess & 301 redirects causing server slowdowns - php

My .htaccess file looks like this:
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.mywebsite\.com [NC]
RewriteRule ^(.*)$ http://mywebsite.com/$1 [L,R=301]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteRule ^resources/([^/\.]+)/?$ page.php?theme=resources&pg=$1 [L]
RewriteRule ^resources/([^/\.]+)/?/([^/\.]+)/?$ page.php?theme=resources&pg=resources&catname=$1&cat=$2 [L]
RewriteRule ^resources/([^/\.]+)/?/([^/\.]+)/?/([^/\.]+)/?$ page.php?theme=resources&catname=$1&cat=$2&pg=$3 [L]
RewriteRule ^albums/([^/\.]+)/?/([^/\.]+)/?$ page.php?theme=albums&pg=albums&albumname=$1&album=$2 [L]
RewriteRule ^albums/([^/\.]+)/?$ page.php?theme=albums&pg=albums [L]
RewriteRule ^leaving-the-site/([^/\.]+)/?$ page.php?theme=leaving-the-site&pg=leaving-the-site&q=$1 [L]
RewriteRule ^([^/\.]+)/?/([^/\.]+)/?$ page.php?theme=$1&pg=$2 [L]
RewriteRule ^([^/\.]+)/?$ page.php?theme=$1&pg=$1 [L]
Everything seems fine, but as we're relaunching the site, we have approximately 110 301 redirects we need to put in place. These are similarly formatted to the following, and added after the above rewrite rules:
RewriteRule ^about/about-the-site$ https://www.mywebsite.com/about-us? [L,NC,R=301]
My problem is that as soon as I have the htaccess file uploaded with all the 301s, it starts to slow down the site, to the point of having 60 second load times within about 10 minutes and then starts timing out.
I remove the 301 redirects, and it recovers. From my research, 301 redirects can slow down a server, but 'not significantly', at least not with less than 1000 lines.
Is there something I should be doing differently?

This is combined HTTPS/SSL & www to non-www Rewrite|Redirect htaccess code specifically for WordPress, but you can modify/customize it for your particular site. I am still looking at your other code...
Edit: Ok I looked at your other code and it is overly complex and the use of question marks in your code may be incorrect. What I recommend you do is use RewriteCond Query String matching code instead of the direction/code you are trying to use now. See this topic for example RewriteCond Query String matching htaccess code examples: Replace "index.php?option=com_k2&view=item&id=" using .htaccess and Regex
# WP REWRITE LOOP START
# Rewrite|Redirect http to https|SSL & www to non-www
RewriteEngine On
RewriteBase /
RewriteCond %{HTTPS} !=on
RewriteCond %{SERVER_PORT} ^80
RewriteCond %{HTTP_HOST} ^www\.domainname\.com$ [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
RewriteRule ^index\.php$ - [L]
# All lines of Rewrite|Redirect code would go here
# if file or directory does not exist then Rewrite to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# WP REWRITE LOOP END

Related

SE crawls booth Directory and /index.php file - how can I prevent that?

I tried to modify my .htaccess file for SEO and do not seem to understand how I can prevent web crawlers to grab double content from my website. Because it seems like Google is indexing my website in two manners:
https://www.example.com/ AND
https://www.example.com/index.php
This is the .htaccess-Code
RewriteEngine On
DirectoryIndex index.php
RewriteBase /
# remove .php; use THE_REQUEST to prevent infinite loops
RewriteCond %{HTTP_HOST} ^www\.get-to-med\.com
RewriteCond %{THE_REQUEST} ^GET\ (.*)\.php\ HTTP
RewriteRule (.*)\.php$ $1 [R=301]
# remove index
RewriteRule (.*)index$ $1 [R=301]
# remove slash if not directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /$
RewriteRule (.*)/ $1 [R=301]
# add .php to access file, but don't redirect
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
RewriteCond %{HTTP_HOST} ^get-to-med.com
RewriteRule (.*) https://www.get-to-med.com/$1 [R=301,L]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
ErrorDocument 404 /diese-seite-existiert-nicht.php
Instead of messing with the .htaccess file endlessly, why not add a canonical tag in the index.php file to the desired version of the page:
<link rel="canonical" href="https://www.example.com/" />
Any search engines following the canonical rule will act accordingly.
As for the .htaccess issue, you've got DirectoryIndex index.php in there so that probably has something to do with it (any time the / directory is requested, the index.php file will be returned; may be stored by Google as such).

Remove/Redirect index.php from url to prevent duplicate urls

Please read the question carefully before marking as duplicate.
We all know, that using in .htaccess:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
we can redirect all traffic to index.php so we can create friendly urls and have one front controller.
Although the question is connected to mod_rewrite the problem is described for Laravel.
The following .htaccess comes by default with Laravel 4 and it works fine:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
RewriteEngine On
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
If we run url mydomain.com/something and have set that route for something properly, some controller will be launched. It works fine so far.
However in Laravel 4 we will be able to reach the same route using mydomain.com/index.php/something. Probably using Laravel url creating we will have no urls with index.php in url but there is some other problem.
For example if our competition would like to make us some harm, they can simple put in Internet single links for urls to mydomain.com/index.php/something, mydomain.com/index.php/something2 and so on and search engines will see duplicate urls.
Of course if we have our custom PHP application, we can do it in PHP without a problem checking simply $_SERVER['REQUEST_URI'] and make 301 redirection. We can of course do the same in Laravel but we have to write this code in PHP each time and probably some developers could say it is bad practice to do it in PHP.
Question is simple: how can I redirect in .htaccess all urls that contain index.php to to the same url without index.php?
Example urls that should be redirected:
mydomain.com/index.php/something should be redirected to mydomain.com/something (something could be anything - can contain any characters)
mydomain.com/index.php should be redirected to mydomain.com
mydomain.com/index.php?anything should be redirected to mydomain.com (anything can contain any characters)
mydomain.com/index.phpanything should be redirected to mydomain.com anything can contain any characters)
Insert these rules just below RewriteEngine On line:
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php[^/] /$1? [L,R=302,NC,NE]
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php(?:/(.*))?$ /$1$2? [L,R=302,NC,NE]
After spending hours I write below code for me and its 100% working
Redirect index.php to non index.php
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^index.php/(.*)$ /$1 [R=301,L]
how can I redirect in .htaccess all urls that contain index.php to to
the same url without index.php?
Add this to your .htaccess
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*)/index\.php [NC]
RewriteRule ^ %1 [R=301,L]
For Nginx, here is the rules :
location / {
rewrite ^/(.*?)index\.php[^/] /$1? redirect;
rewrite ^/(.*?)index\.php(?:/(.*))?$ /$1$2? redirect;
}
This solved my problem to force https & remove index.php from the url in Kohan 2.3
RewriteEngine On
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php[^/] /$1? [L,R=302,NC,NE]
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php(?:/(.*))?$ /$1$2? [L,R=302,NC,NE]
RewriteRule ^(application|system) - [F,L]
RewriteCond %{THE_REQUEST} /index.php [NC]
RewriteRule ^(.*)index\.php$ /$1/ [R=301,L,NC,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?!localhost$|127\.0\.0\.1$)(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE]

Redirect from .htaccess does not work

I have a website and i want to make it always show as www.mysite .com i put that code in .htaccess :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
now the url shows as www but the website is not shown the browser said "This webpage has a redirect loop"
Note: .htcaccess do not have any code but this few lines i wrote
does i did anything wrong or i miss something??? please help
Edit:
before I add the above code the .htaccess had the following code but not direct to www i remove it :
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
RewriteCond %{QUERY_STRING} ^m=1$
RewriteRule (.*) $1? [R=permanent]
# END WordPress
could that be updated to solve my problem?
if you are doing it at windows server it will not work if it is window you have to create web.config file n for linux it should be .htaccess
Ok so Wordpress is also there. Make sure to do these 2 things:
Put your 301 rule above WP's rules i.e. just below RewriteBase line
Update WP settings to have your site address with www
RewriteCond %{HTTP_HOST} ^[^.]+\.[^.]+$
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [L,R=301]
or
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301]

Simple mod_rewrite rule not working [L]

So this is my first time doing mod_rewrite and I'm using tutorials and generators and it's been going okay so far except for the last line below which if I haven't made any mistake should redirect about.php to about/
Anybody know why it doesn't ?
All the other rules are working without issues (I did double check the page existed, I tried to add a slash before about.php as my website is on a server with multiple websites...)
Options +FollowSymLinks
#Sub-dir e.g: /cmsms
RewriteBase /
#redirect www.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.metareviewr.com
RewriteRule (.*) http://metareviewr.com/$1 [R=301,L]
#RewriteRule ^show/([^/]*)/$ /tvshow.php?id=$1 [L]
RewriteRule ^show/([^/]*)/([^/]*)/$ /tvshow.php?id=$1&?name=$2 [L]
# Removes index.php from ExpressionEngine URLs
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+/)*index\.php\ HTTP/
RewriteRule ^(([^/]+/)*)index\.php$ http://metareviewr.com/$1 [R=301,L]
RewriteRule ^about/$ about.php [L]
This should work
RewriteRule ^about.php$ about/ [L,R=301]

RewriteRule violates while switching from https to http

I write a lot of RewriteRule in my .htaccess file , but problem occurs when I switch from https to http pages; it does not follow these rules
NOTE : everything working fine on localhost , issues are on server <---- UPDATE
Here is my website , currently all links display as per RewriteRule*
for e.g. about us page link display as
http://www.mywebsite.com/about
BUT
if I am at login page ( which is on https ) and click on about us page then it turns into below.
http://www.mywebsite.com/about?slug=about_us
or if I click on any category on left panel then it comes as
http://www.mywebsite.com/auction/category/1?cid=1
Note : even mouse hovering on pages display rewrite link
below is .htaccess file with needed information.
IndexIgnore *
RewriteEngine on
Options +FollowSymLinks
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^auction/category/([0-9]+)/?$ bids.php?cid=$1 [NC]
RewriteRule ^login/?$ login.php [NC]
RewriteRule ^register/?$ register.php [NC]
RewriteRule ^logout/?$ logout.php [NC]
# static pages
RewriteRule ^about/?$ page.php?slug=about_us [NC]
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} /login [OR]
RewriteCond %{REQUEST_URI} /do_login.php
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NC,L,QSA]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule \.(gif|jpe?g|png|ico|css|js)$ - [NC,L]
# traffic to http:// except some pages
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(/login|/do_login.php)
RewriteRule ^(.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NC,L,QSA]
Note : Here is complete .htaccess file
Please tell me where I am wrong/missing ?
I Also have few more confusion
If i change the case of rewrite URL ( Login or lOgin or logiN ) then it gives error?
Is it good practice to write [NC,L] with all RewriteRule?
Exactly when I should write [QSA] ?
UPDATE
After suggestions from all answers, changing in RewriteRule almost fixed all issue but now there is one last issue.
/login URL always changed into /login.php.
below is my updated .htaccess
IndexIgnore *
Options -MultiViews
Options +FollowSymLinks
#mod_rewrite
RewriteEngine on
RewriteBase /
# Rewrite www to non www
RewriteCond %{HTTP_HOST} ^www.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]
# minimize the css on all http:// pages
<IfModule mod_rewrite.c>
RewriteCond %{HTTPS} off
RewriteRule ^(.*).css$ /csszip.php?file=$1.css [L]
</IfModule>
#switch over http to https
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} (/login|/do_login)\.php [NC]
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule \.(gif|jpe?g|png|ico|css|js)$ - [NC,L]
# traffic to http:// except some pages
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(/login|/do_login)\.php [NC]
RewriteRule ^(.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^login/?$ login.php [NC]
RewriteRule ^register/?$ register.php [NC]
# ...many other rules...with [NC] falg
RewriteRule ^auction/category/([^/.]+)/?$ bids.php?cid=$1 [NC]
RewriteRule ^about/?$ page.php?slug=about_us [NC]
# ...many more rules.... with [NC] flag
HTTPS suggestion
For your HTTPS issue I would match on port or HTTPS as there are known apache problems relating to the HTTPS tag.
To cover this match on both (as shown in your edited answer)
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
##REWRITE RULE
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} = on
##REWRITE RULE
A valid point is also that %{REQUEST_URI} isn't affected by any substitutions.
The way you are using it at the moment, if any rule matches you will send them to the original url (before any substitution started).
If you want to take the url after and substition and matching use $1
Answers to your further questions:
If I change the case of rewrite URL then it gives error?
This is because your [NC] isn't on the rewrite cond for the HTTPS section of your .htaccess
You match RewriteCond %{REQUEST_URI} /login [OR] this is only looking for lower case login, if you want to accept uppercase login append NC.
Is it good practice to write [NC,L] with all RewriteRule?
No, it depends what you want to do [NC] says don't match case on this rule, if you don't want to match case on that rule (or condition) then add it.
Not matching the case with [NC] means site.com/login.php = sYte.cOm/LoGin.PHP
[L] means if this is true, stop processing everything
Exactly when I should write [QSA] ?
QSA applies when you have a ? in your substitution and you want to append toe old string to the new URL
Consider the following rule:
RewriteRule /pages/(.+) /page.php?page=$1 [QSA]
With the [QSA] flag, a request for /pages/123?one=two will be mapped to /page.php?page=123&one=two. Without the [QSA] flag, that same request will be mapped to /page.php?page=123 - that is, the existing query string will be discarded.
Do use QSA if you want to keep any additional get arguments.
Another further question
/login URL always changed into /login.php
The only way for this to happen is if you have a redirect [R=301] somewhere in your code, the only place I can see that is this section:
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
RewriteCond %{REQUEST_URI} (/login|/do_login)\.php [NC]
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Where this will only match the following URL's
.php, /login.php, /do_login.php
I believe the culprit is as I outlined in the first response with %{REQUEST_URI}
Your code essentially says, if these conditions are met, send them to https://theurltheywentto, which is not what you want to do, you want to send them to /login.
Have you tried using (as mentioned in my https section)
RewriteRule ^(.*) https://%{HTTP_HOST}/login [R=301,L]
Or perhaps (if you have /do_login) and other options
RewriteRule ^(.*).php https://%{HTTP_HOST}/$1 [R=301,L]
Where test.com/do_login.php will become https://test.com/do_login
How about you try:
# Rewrite to https
RewriteCond %{REQUEST_URI} (/login|/do_login)\.php [NC]
RewriteCond %{HTTPS} != on
RewriteRule ^(.*)\.php https://%{HTTP_HOST}/$1 [R=301,L]
I think this might be of your help
.htaccess redirect https to http not working
and for last question this might be of your help
http://httpd.apache.org/docs/current/rewrite/flags.html and
http://www.addedbytes.com/download/mod_rewrite-cheat-sheet-v2/png/
EDIT:
You can try using
RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{SERVER_PORT} !^443$
instead of
RewriteCond %{HTTPS} on [NC]
RewriteCond %{HTTPS} off [NC]
For detail
Please see this link, someone had similar problem. Please see second reply of the post
http://www.webmasterworld.com/apache/3228459.htm
you can solve this by creating the domain alias
You can't do it within .htaccess, but within a http.conf <VirtualHost> section you can use the ServerName and ServerAlias directives to accomplish this.
Your confusion over /about is due to redirecting to %{REQUEST_URI}, which isn't changed as you make substitutions. Capture the URI and use $1 if you don't really want the URI as it started uring this round of rewrite processing.

Categories