Rewrite subdomain to folder keeping the URL unchanged

5,357
RewriteRule ^(.*)$ http://example.com/%1/$1 [L,NC,QSA]

When you specify an absolute URL (scheme + hostname) in the RewriteRule substitution it will implicitly trigger an external redirect - which is what you are seeing.

However, if the subdomain(s) and main domain are all on the same shared hosting account (ie. the same filesystem) then you shouldn't have to explicitly specify the full domain in the susbstitution, just specify the file system path.

For example:

RewriteRule (.*) /%1/$1 [L]

The NC and QSA flags would seem to be superfluous here. The query string is appended by default, unless you explicitly include a query string in the substitution. And the pattern anchors (^ and $) are not required either when using a match everything .* pattern.


UPDATE#1: The first RewriteRule would seem to be superfluous. This is a wildcard subdomain, so I assume the subdomain points to the same document root as the main domain.

What you are really trying to do is internally rewrite http://anything.example.com/par1/par2 to /anything/index.php?a=par1&b=par2 on the same subdomain.

Try the following instead:

RewriteEngine on
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com [NC]
RewriteRule ^([^/.]+)/([^/.]+)/?$ %1/index.php?section=$1&page=$2 [L,QSA]

The QSA flag is required here, if the original request (pretty URL) could have a query string, which needs to be passed through.

No need to escape the dot in a character class in order to match a literal dot.

The RewriteCond directive checking against the REDIRECT_STATUS environment variable prevents a potential rewrite loop (which would result in a 500 error in the browser).

UPDATE#2: To avoid the explicit use of the domain (eg. example.com) then you could just match the first domain segment, ie. upto the first dot. For example:

RewriteCond %{HTTP_HOST} ^([^.])+

However, this would also match the main apex domain (or www), unless you already have a directive to block that. I assume accessing the main domain like this would strictly be invalid? However, this might be OK if your script handles such an invalid request with a 404?

Or, to match only subdomains of the main domain, except for www then try:

RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^([^.])+\.[a-z-]\.(com|co\.uk|net) [NC]

You would need to add the TLDs as required (maybe that could be generalised further?).

Share:
5,357

Related videos on Youtube

Roman Matveev
Author by

Roman Matveev

Updated on September 18, 2022

Comments

  • Roman Matveev
    Roman Matveev over 1 year

    I'm on a cheap shared hosting with Apache and I'm trying to do the following rewrite with .htaccess:

    • http://anything.example.com/par1/par2 => http://example.com/anything/index.php?a=par1&b=par2

    To do this I have the following .htaccess file in the root directory:

    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
    RewriteRule ^(.*)$ http://example.com/%1/$1 [L,NC,QSA]
    RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ $1/index.php?section=$2&page=$3 [L]
    

    And this works actually. The problem is that if I put http://digitalcameras.example.com/nikon/123 to the web browser address string and press Enter, the string becomes like this:

    http://example.com/digitalcameras/nikon/123
    

    (Note that the digitalcameras part moved from the beginning to the middle).

    index.php placed in the /digitalcameras folder.

    So the question is: can I do the same thing without changing the address in the browser?

    • MrWhite
      MrWhite over 7 years
      I assume the subdomain and main domain point to the same filesystem? Where does the subdomain point to on the filesystem, in relation to the main domains document root?
    • Roman Matveev
      Roman Matveev over 7 years
      @w3dk if I understand your question right than the answer is yes. Please see my comment to your answer. BTW - thank you for editing!
  • Roman Matveev
    Roman Matveev over 7 years
    I made the changes: RewriteRule ^(.*)$ /home/c/username/public_html/%1/$1 [L,NC,QSA]. But I've got Internal server error now :( The changes was as you intended?
  • MrWhite
    MrWhite over 7 years
    A root-relative substitution is relative to the document root, rather than the server root. So it should probably just be /%1/$1.
  • MrWhite
    MrWhite over 7 years
    Presumably this .htaccess file is in the root directory of the main domain and not the root directory of the subdomain? So, the subdomain simply points to a subdirectory off the main domains document root?
  • Roman Matveev
    Roman Matveev over 7 years
    Yes. .htaccess is in the root directory (/home/c/username/public_html/. I made the changes (RewriteRule ^(.*)$ /%1/$1 [L,NC,QSA]) still have 500 error.
  • Roman Matveev
    Roman Matveev over 7 years
    Maybe it would be better to join both rewrite rules into one? So by ONE rule redirect subdomain.example.com/1/2 to example.com/index.php?a=subdomain&b=1&c=2? Is it possible?
  • Roman Matveev
    Roman Matveev over 7 years
    Yes - it is wildcard subdomain. RewriteRule (.*) /%1/$1 [L] did not worked :( I will try to do a single rule rewrite to work...
  • MrWhite
    MrWhite over 7 years
    Yes, the first RewriteRule would seem to be superfluous and can be "joined" with the second. I'll update my answer. (Sorry, I don't think I read it your question properly the first time!)
  • MrWhite
    MrWhite over 7 years
    Another update to avoid a rewrite loop (were you getting a rewrite loop?).
  • Roman Matveev
    Roman Matveev over 7 years
    No! There was no loop. All worked flawlessly!!! :)))) Is it possible to avoid of explicit use of domain name to make the htaccess "universal"?
  • MrWhite
    MrWhite over 7 years
    I've updated my answer with a more "universal" domain check.