One rewrite rule or multiple ones in htaccess

.htaccessmod-rewrite

I have a main domain, a couple of addon domains and recently went HTTPS. This is working OK for me but I would like your opinion:

## All http requests to the relative https url
RewriteCond %{SERVER_PORT} 80 [OR]
## redirect the other domains and the non www main main domain
RewriteCond %{HTTP_HOST} ^domain3.com [OR]
RewriteCond %{HTTP_HOST} ^www.domain3.com [OR]
RewriteCond %{HTTP_HOST} ^domain2.com [OR]
RewriteCond %{HTTP_HOST} ^www.domain2.com [OR]
RewriteCond %{HTTP_HOST} ^maindomain.com
## this stuff is for SSL
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
## i send them all to the https main domain
RewriteRule ^(.*)$ https://www.maindomain.com/$1 [L,R=301]

Is this a better approach to having a rewrite rule for each condition?

Best Answer

There certainly isn't a need for multiple RewriteRule directives. That would only complicate things and be less efficient. If you have multiple rules (for each condition) then each rule would at least be processed, even if you were already at the canonical protocol + host.

However, you seem to be redirecting every other domain. Everything that is not www.maindomain.com. If this is the case then you can simplify this rule and do away with the multiple conditions. For example:

## All http requests to the relative https url
RewriteCond %{SERVER_PORT} 80 [OR]
## redirect all the other non-canonical domains
RewriteCond %{HTTP_HOST} !^www\.maindomain\.com
## this stuff is for SSL
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
## i send them all to the https main domain
RewriteRule (.*) https://www.maindomain.com/$1 [L,R=301]

So, this now says... if HTTP or not www.maindomain.com then redirect to HTTPS and www.maindomain.com. Instead of specifically checking for every non-canonical host, you are just checking to see that it is not the canonical host.

No need for the start and end anchors if you are capturing the entire URL-path anyway. ie. (.*) is the same as ^(.*)$.

Or, you could avoid the regex capturing and just use the REQUEST_URI server variable instead (which notably starts with a slash). For example:

RewriteRule ^ https://www.maindomain.com%{REQUEST_URI} [L,R=301]
## this stuff is for SSL
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$

This looks like the carbuncle that cPanel (automatically) injects before every RewriteRule when renewing SSL certs. If you have a lot of RewriteRule directives in .htaccess this makes for an incredibly bloated .htaccess file. (It can also expose vulnerabilities that were not evident previously.) I don't know why they don't separate these conditions into a single block at the start of the file and negate (ie. invert) them instead? For example:

# START: this stuff is for SSL
RewriteCond %{REQUEST_URI} ^/[0-9]+\..+\.cpaneldcv$ [OR]
RewriteCond %{REQUEST_URI} ^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^ - [L]
# END: this stuff is for SSL

## All http requests to the relative https url
RewriteCond %{SERVER_PORT} 80 [OR]
## redirect all the other non-canonical domains
RewriteCond %{HTTP_HOST} !^www\.maindomain\.com
## i send them all to the https main domain
RewriteRule (.*) https://www.maindomain.com/$1 [L,R=301]
Related Topic