1

I got stuck on using Apache's RewriteCond and RewriteRule conditions. I usually don't use them a lot and mostly the documentation provides me enough information to produce a solution by my self. This time however I got stuck on how to combine more then 1 rewrite situation.

On Apache 2.4.17 I have a virtual host with serveral ServerAliases all pointing to the same ServerName and directory. Every configured ServerAlias should redirect to the ServerName domain. So when I visit sub1.domain.com, sub2.domain.com or sub3.domain.com it all should be HTTP 301 redirected to www.domain.com.

Also I want to redirect all URL to the same PHP inputfile. For example: www.domain.com/news/1 should be internally redirected to the index.php file at the documentroot of the virtalhost without changing the URL in the user's webbrowser.

Above situations do work on it's own, but when I try to combine the situations at the .htaccess file things go wrong.

Example of my domain redirecting:

AcceptPathInfo On
Options +MultiViews

Options +FollowSymLinks  
RewriteEngine On  

# Following solution inspired by https://makandracards.com/makandra/922-apache-redirect-all-requests-from-one-host-to-another
RewriteCond %{HTTP_HOST} !^www.domain.com$
RewriteRule ^(.*)$ "https://www.domain.com/$1" [NC,QSA,R=301]

This works very well.

And this is the code I normally use to redirect all URL internally to index.php at the documentroot to be able to generate dynamic content based on the URL:

AcceptPathInfo On
Options +MultiViews

Options +FollowSymLinks  
RewriteEngine On  

RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f  

RewriteRule ^.*$ ./index.php

This works also very well. The request don't get forwarded at the users browsers to index.php but only internal.

When I try to combine both redirects:

AcceptPathInfo On
Options +MultiViews

Options +FollowSymLinks  
RewriteEngine On  

# Following solution inspired by https://makandracards.com/makandra/922-apache-redirect-all-requests-from-one-host-to-another
RewriteCond %{HTTP_HOST} !^www.domain.com$
RewriteRule ^(.*)$ "https://www.domain.com/$1" [NC,QSA,R=301]

RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f  

RewriteRule ^.*$ ./index.php

Then things go wrong. All requests on the other domains (for example sub1.domain.com, sub2.domain.com/test, etc.) results in an Apache error:

Moved Permanently

The document has moved here.

Additionally, a 301 Moved Permanently error was encountered while trying to use an ErrorDocument to handle the request.

While www.domain.com/test correctly serves the content of index.php at the document root.

When I try to change the order of the conditions and rules:

AcceptPathInfo On
Options +MultiViews

Options +FollowSymLinks  
RewriteEngine On  

RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f  

RewriteRule ^.*$ ./index.php

# Following solution inspired by https://makandracards.com/makandra/922-apache-redirect-all-requests-from-one-host-to-another
RewriteCond %{HTTP_HOST} !^www.domain.com$
RewriteRule ^(.*)$ "https://www.domain.com/$1" [NC,QSA,R=301]

Then sub1.domain.com got correctly redirected at the user's browser to www.domain.com, but when I append a URI to it like sub1.domain.com/test then it got redirected to www.domain.com/index.php instead of www.domain.com/test and only internally fetching the content of index.php at the documentroot.

Requesting www.domain.com/test directly in this case does work well: the content of index.php at the documentroot is being displayed instead of redirecting the user to index.php.

I believe it have to do something with some flags, but don't know in which way to apply them. Who can explain me on what things I have to pay attention to?

  • If you don't need to convert your non-existant pages to index.php externally (I mean, you do not need uour clients to see index.php in their browser's address bar) you could use your first try but adding [PT] to the index.php rule. Also, you need to add an L flag to the domain rule: [QSA,R=301,L], NC is not needed in the rewrite since you are capturing everything with .* – NuTTyX Oct 23 '16 at 10:43
0

I think I already solved the issue by my self bij adding the [L] flag to both the RewriteRule lines.

This is my htaccess file right now:

AcceptPathInfo On
Options +MultiViews

Options +FollowSymLinks  
RewriteEngine On 

# Following solution inspired by https://makandracards.com/makandra/922-apache-redirect-all-requests-from-one-host-to-another
RewriteCond %{HTTP_HOST} !^www.domain.com$
RewriteRule ^(.*)$ "https://www.domain.com/$1" [NC,QSA,R=301,L]

RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f  

RewriteRule ^.*$ ./index.php [L]

As far as I understand Apache will now first look at

RewriteCond %{HTTP_HOST} !^www.domain.com$

and then execute

RewriteRule ^(.*)$ "https://www.domain.com/$1" [NC,QSA,R=301,L]

Since that RewriteRule has the [L] flag set Apache won't check for any other rules.

When the complete URL does not met the first RewriteCond Apache will skip that RewriteCond / RewriteRule combination and go the part with

RewriteCond %{SCRIPT_FILENAME} !-d  
RewriteCond %{SCRIPT_FILENAME} !-f  

RewriteRule ^.*$ ./index.php [L]

Which only internal redirects. And now it's not getting combined with the first RewriteRule because that RewriteRule is getting skipped because of it's [L] flag.

Am I right? Can someone confirm or deny this explanation? Or maybe clarify it?

  • "As far as I understand Apache will now first look at" - this isn't strictly true. The RewriteRule directive is actually processed first - at least in part. Apache first processes the RewriteRule pattern. Only if this matches the URL-path, does the rewrite engine step back and start processing the RewriteCond directives that precede it. If all the conditions are successful then the RewriteRule substitution occurs. This is an important concept as it means you can use backreferences from the RewriteRule pattern in preceding conditions. – DocRoot May 3 at 21:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.