Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

In my root folder, the following captures https://example.org and http://example.org and redirects to its respective version (http or https) with the www added back in. (It's a requirement they had with an advertisement system.)

The problem however is when a subdir uses the "direct everything at the index.php" technique you see with MVC coding in PHP. It completely ignores the www rule.

My problem is that I need to make the subdirs, even if they have an .htaccess, to use the rule of the root .htaccess for the www redirect. What can I do to either ensure a subdir .htaccess applies the www rule from either the master, or at least edit the subdir .htaccess ?

# ROOT .htaccess FILE
RewriteEngine on

# IF HTTPS OFF AND NO WWW, REDIRECT TO HTTP://WWW.*
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ http://www.example.org/$1 [R=301,L]

# IF HTTPS ON AND NO WWW, REDIRECT TO HTTPS://WWW.*
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ https://www.example.org/$1 [R=301,L]

The one in some few subdirs looks like:

# SUBDIR .htaccess FILE
Options All +FollowSymLinks -Indexes -Multiviews

# BLOCK ROBOTS AND SPIDERS FROM SCANNING CERTAIN FILES
IndexIgnore .htaccess *~ *.txt *.sql *.xml

# BLOCK SOME COMMON FILE TYPES FROM END USERS
<FilesMatch "\.(sql|xml|txt|htaccess)">
    Deny from all
</FilesMatch>
<FilesMatch ".*~$">
    Deny from all
</FilesMatch>

RewriteEngine On

# BESIDES BLOCKED FILES ABOVE, OR FILES WE PHYSICALLY HAVE IN THIS DIRECTORY,
# REDIRECT ALL OTHER OUTPUT TO index.php AND PASS ALL URL PARAMETERS IN FULL.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [QSA]

Note that I tried something like this in the subdir .htaccess files, but it failed -- I ended up with 404s in the subdir paths.

# SUBDIR .htaccess FILE
Options All +FollowSymLinks -Indexes -Multiviews

# BLOCK ROBOTS AND SPIDERS FROM SCANNING CERTAIN FILES
IndexIgnore .htaccess *~ *.txt *.sql *.xml

# BLOCK SOME COMMON FILE TYPES FROM END USERS
<FilesMatch "\.(sql|xml|txt|htaccess)">
    Deny from all
</FilesMatch>
<FilesMatch ".*~$">
    Deny from all
</FilesMatch>

RewriteEngine On

# IF HTTPS OFF AND NO WWW, REDIRECT TO HTTP://WWW.*
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ http://www.example.org/$1 [R=301,L]

# IF HTTPS ON AND NO WWW, REDIRECT TO HTTPS://WWW.*
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ https://www.example.org/$1 [R=301,L]

# BESIDES BLOCKED FILES ABOVE, OR FILES WE PHYSICALLY HAVE IN THIS DIRECTORY,
# REDIRECT ALL OTHER OUTPUT TO index.php AND PASS ALL URL PARAMETERS IN FULL.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [QSA]

EDIT:

For example...

I want to go to:

 1 http://example.org/
 2 http://www.example.org/
 3 https://example.org/
 4 https://www.example.org/
 5 http://example.org/test/something.php
 6 http://example.org/test/
 7 https://www.example.org/test/
 8 https://www.example.org/test/update-user

...and the test folder is a PHP MVC platform so it uses the "direct everything at index.php" technique inside that folder.

...and so I want the above to translate to:

 1 http://www.example.org/
 2 http://www.example.org/
 3 https://www.example.org/
 4 https://www.example.org/
 5 http://www.example.org/test/something.php
 6 http://www.example.org/test/
 7 https://www.example.org/test/
 8 https://www.example.org/test/update-user

It's the "www. subdomain no matter what" strategy. And note that it kept the https intact if that was used.

The trouble is that the test folder's .htaccess file ignores what's in the root .htaccess file, and I don't know how to edit the test folder's .htaccess file such that it can do the www. thing properly. I attempted it (as I demonstrated above in the third code sample) and I ended up with 404 errors.

share|improve this question

3 Answers 3

A simple solution would be to create a separate root folder for the example.org site.

share|improve this answer
    
I'm afraid you may not understand what I'm saying. I will add an EDIT to explain better. –  ServerChecker Apr 27 '12 at 6:48
    
I think I understood your question. What I was saying is that instead of fiddling around with having everything in the same root directory, create a second virtualhost for example.org where you put the rewrite rules and redirect to the www virtualhost. –  Oliver Apr 27 '12 at 6:58
    
But doesn't that mean that I connect to like example.org/test/update-user (where the PHP MVC app engages) and then it would redirect to example.org and stop. That's not the desired result. And remember -- I only have .htaccess files at my use here. I cannot edit the httpd.conf on a shared hosting plan. –  ServerChecker Apr 27 '12 at 7:09
    
If you don't have possibility to create a new virtual host, and your hoster has a recent version of Apache (>2.3.9), then you might be able to solve the problem using the ENDflag in your rewrite rule:RewriteRule ^(.*)$ http://www.example.org/$1 [R=301,END] –  Oliver Apr 27 '12 at 9:29
    
Unfortunately on shared hosting plans running the latest CentOS release, you often see Apache 2.2.3. That's what they're running. It didn't work. –  ServerChecker Apr 27 '12 at 16:27

The fix is simple. I almost had it in my example I provided in the original question. The following code takes the subdir test's .htaccess file, which has a PHP MVC structure in it that uses the "direct everything at the index.php file", detects that "www." prefix wasn't used, and tacks the "www." prefix back on. My client's advertising campaigns specifically required that "www." added in because the purchased campaign could only use one domain, not two, without additional expense.

However, I was thwarted in my testing because I forgot about browser cache and 301 permanent redirects. If one connected to the page previously when experimenting, you may need to clear your browser cache. This is because a 301 redirect was used during experimentation, and this tells the browser to cache that redirect locally. This is why my tests were failing. A 302 temporary redirect wouldn't do that, but actually in this case a 301 permanent redirect is better because it's faster in browser connection time. A 301 redirect will tell your browser (look in your cache before you go to this url so that you know where to go), while a 302 redirect will tell your browser (I will decide on the fly where you should redirect).

The fix is to add the subdir information into the .htaccess file. So, if I have a subdirectory named "test" with its own .htaccess file inside, then I need to add that information in. Notice the /test/ is added in below. And if I had this file inside /test/test2, then I would need to add /test/test2/ into that .htaccess file there. Get it?

# SUBDIR .htaccess FILE
Options All +FollowSymLinks -Indexes -Multiviews

# BLOCK ROBOTS AND SPIDERS FROM SCANNING CERTAIN FILES
IndexIgnore .htaccess *~ *.txt *.sql *.xml

# BLOCK SOME COMMON FILE TYPES FROM END USERS
<FilesMatch "\.(sql|xml|txt|htaccess)">
    Deny from all
</FilesMatch>
<FilesMatch ".*~$">
    Deny from all
</FilesMatch>

RewriteEngine On

# IF HTTPS OFF AND NO WWW, REDIRECT TO HTTP://WWW.*
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ http://www.example.org/test/$1 [R=301,L]

# IF HTTPS ON AND NO WWW, REDIRECT TO HTTPS://WWW.*
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^example.org$
RewriteRule ^(.*)$ https://www.example.org/test/$1 [R=301,L]

# BESIDES BLOCKED FILES ABOVE, OR FILES WE PHYSICALLY HAVE IN THIS DIRECTORY,
# REDIRECT ALL OTHER OUTPUT TO index.php AND PASS ALL URL PARAMETERS IN FULL.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [QSA]
share|improve this answer

One excellent approach here, as Oliver appears to be alluding to, is to create a separate VHost for the non-WWW site, and supply it with a global redirect:

<VirtualHost *:80>
    ServerName example.org

    RedirectPermanent / http://www.example.org/
</VirtualHost>

Failing that, since you're already modifying subordinate .htaccesses, just add this to each of the subordinates:

RewriteOptions inherit

Much cleaner than having to maintain the same root-level rewrite code in multiple .htaccesses.

share|improve this answer
    
Yes, much cleaner, but on a shared hosting plan I have no way to edit the httpd.conf, and the above virtual host directive is blocked in my .htaccess by the shared hosting plan. –  ServerChecker Apr 28 '12 at 6:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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