3

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?

  • 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? – MrWhite Jan 17 '17 at 20:56
  • @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 Jan 17 '17 at 20:58
1
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?).

  • 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? – Roman Matveev Jan 17 '17 at 20:59
  • A root-relative substitution is relative to the document root, rather than the server root. So it should probably just be /%1/$1. – MrWhite Jan 17 '17 at 21:01
  • 1
    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 Jan 17 '17 at 21:18
  • 1
    No! There was no loop. All worked flawlessly!!! :)))) Is it possible to avoid of explicit use of domain name to make the htaccess "universal"? – Roman Matveev Jan 17 '17 at 21:33
  • 1
    I've updated my answer with a more "universal" domain check. – MrWhite Jan 17 '17 at 21:51

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.