18

I'm working on a virtual domain system. I have a wildcard DNS set up as *.loc, and I'm trying to work on my .htaccess file. The following code works:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?example\.loc$ [NC]
RewriteCond %{REQUEST_URI} !^/example/
RewriteRule (.*) /example/$1 [L,QSA]

But, I want this to work with anything I put in. However, I need the %{REQUEST_URI} checked against the text found as the domain. I tried using this code:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?([a-zA-Z0-9-]*.)?([a-zA-Z0-9-]+)\.loc$ [NC]
RewriteCond %{REQUEST_URI} !^/%3/
RewriteRule (.*) /%3/$1 [L,QSA]

But the line RewriteCond %{REQUEST_URI} !^/%3/ causes my code to throw an Internal Server Error. I understand this is because of the %N in my code but is there a way I can work with it? I need this line, otherwise, my code fails from internal redirects.

I hope this makes sense to someone. All I need is to be able to backreference a RewriteCond in a following RewriteCond.

Stack Underflow
  • 2,363
  • 2
  • 26
  • 51
Connor Deckers
  • 2,447
  • 4
  • 26
  • 45

1 Answers1

48

There's 2 things that you are doing wrong here.

First, your %{HTTP_HOST} regex is no good. You need to escape the . dots otherwise they'll be treated as "any character that's not a newline". This essentially makes the %3 backreference the last character of the hostname before the TLD (e.g. http://blah.bar.loc, %3 = r).

Second, you can't use backreferences in the regex of a RewriteCond, only the left side string, it's sort of a weird limitation. However, you can use the \1 references, in the regex so that you can construct a clever left side string to match against. Something like %3::%{REQUEST_URI} and then you can match like this: !^(.*?)::/\1/?. This regex essentially says: "match and group the first block of text before the ::, then make sure the block of text following the :: starts with /(first block)".

So your rules should look like this:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?([a-zA-Z0-9-]*\.)?([a-zA-Z0-9-]+)\.loc$ [NC]
RewriteCond %3::%{REQUEST_URI} !^(.*?)::/\1/?
RewriteRule (.*) /%3/$1 [L,QSA]
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • 1
    Cheers! I have no idea what the hell that line really does, but it works. For now, I'm happy with that. Your help is hugely appreciated :) – Connor Deckers Apr 13 '13 at 00:10
  • 3
    Where on earth is this documented. This answer deserves so many more up-votes. I vote we unaccept the answer, put bounty on, and reaccept. – Jim Rubenstein Jul 23 '13 at 18:21
  • 1
    Is there a link to any documentation? What :: are for? – Edik Mkoyan Feb 18 '19 at 09:23
  • 1
    @EdikMkoyan the "::" is just a way to match against the `%3::%{REQUEST_URI}`. You can use whatever you want but it just needs to be unlikely to show up as part of the URI – Jon Lin Feb 18 '19 at 17:24