Reputation: 32869
Ok, so I'm doing a mod_rewrite, and I'm in a situation to where I need to match any subdomain except for one. It starts out looking like this.
RewriteCond %{HTTP_HOST} ^([^\.]+)\.example\.com$ [NC]
So that matches and captures a single subdomain, no periods. But let's say I don't want to match the submdomain named 'dog'. I tried to do this with a negative lookahead like so.
RewriteCond %{HTTP_HOST} ^((?!dog)[^\.]+)\.example\.com$ [NC]
This works, for the most part. dog.example.com no longer matches, which is good. However, doggies.example.com also no longer matches. That is not good.
I was able to fix this by using a negative lookahead combined with a negative look-behind like so.
RewriteCond %{HTTP_HOST} ^((?!dog)[^\.]+(?<!dog))\.example\.com$ [NC]
This works. It works perfectly, as far as I can tell. The thing is, I can't believe that is the best way to achieve this match. A lookahead and a look-behind? Really? What is the "correct" way to achieve an equivalent expression?
Upvotes: 3
Views: 3359
Reputation: 655129
If you want to use a negative lookahead, you need to anchor the expression to the dot:
RewriteCond %{HTTP_HOST} ^((?!dog\.)[^.]+)\.example\.com$ [NC]
Otherwise anything that starts with dog
wouldn’t be allowed.
The same applies to the negative lookbehind:
RewriteCond %{HTTP_HOST} ^([^\.]+(?<!^dog))\.example\.com$ [NC]
Anchoring it to the start of the string with ^
will ensure that something that just ends with dog
like catdog
will still be allowed.
Another solution similar to what Vinko Vrsalovic mentioned is to test what the first submatch holds:
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond %1 !^dog$
Upvotes: 9
Reputation: 340151
You can simplify things a lot using the negation operator of RewriteCond, like this:
RewriteCond %{HTTP_HOST} ^([^\.]+)\.mydomain\.com$ [NC]
RewriteCond %{HTTP_HOST} !^dog\. [NC]
Upvotes: 1