Forum Moderators: phranque
RewriteEngine on
RewriteCond %{HTTP_HOST} ^([a-z0-9]+)\..+\..*$ [NC]
RewriteCond /path/to/public_html/%1!-d
RewriteCond /path/to/public_html/%1!-l
RewriteCond /path/to/public_html/subs/%1.php -f
RewriteRule ^(.*)$ [www,mydomain.info...]
this gives me an internal server error when I request [foo.mydomain.com...] and foo.php exists in subs. I've tried it without the www and withouth [www...] and both seem to just go away and hang.
Any ideas whats wrong or how to fix it?
Welcome to WebmasterWorld!
Yes the problem is that you can't have a variable back-referenced in the pattern of a RewriteCond. You can create a back-reference in the pattern, but you can't use one.
Well, sort of... There is a "tricky" work-around, which we discussed in a thread titled Rewriting arbitrary subdomains to subdirectories [webmasterworld.com], related to your project. You will have to add your "check for directory exists logic" to the code, but the basic technique may be helpful.
Jim
So going back to first principles. I have a php script which from time to time creates and writes a new php script called newsubdomain and puts it in directory subs. Now anytime someone requests newsubdomain.mydomain.info I want them to see subs/newsubdomain.php without any external redirect.
If there's no file, then the default apache behaviour returns index.htm which is cool.
As far as I can tell the rewritecond clauses are working. If there's no file in the subs directory I see the default index. When there is a file, apache hangs, presumably disappearing into an endless recursion.
How is this prevented?
So, you'll need to integrate this function of the code I cited into your subdomain->subdirectory RewriteRule.
Jim
# rewrite only if host is not empty
RewriteCond %{HTTP_HOST}--space--!^$
# rewrite only if host is not main server
RewriteCond %{HTTP_HOST}--space--!^(www\.)?mydomain\.info$ [NC]
# extract subdomain and path, ignore leading www
RewriteCond %{HTTP_HOST}<->%{REQUEST_URI} ^(www\.)?([^.]+).*<->/([^/]+)
# dont rewrite if already rewritten
RewriteCond %3<->%4!^(.*)<->subs/\1.php$ [NC]
# check for directory or symlink
RewriteCond /path/to/public_html/%3--space--!-d
RewriteCond /path/to/public_html/%3--space--!-l
# check file exists
RewriteCond /path/to/public_html/subs/%3.php -f
RewriteRule ^(.*)$ /subs/%3.php
I've tried commenting rewriteconds until I'm left with just the rule, and I still get a 500 error.
any ideas?
[Tue Sep 28 01:18:05 2004] [alert] [client 195.137.20.104] /home/dawnray/public_html/.htaccess: RewriteCond: cannot compile regular expression '!^http://(www\.)?([^\.]\.mydomain\.info/.*$'
dont know what the #039 is - the error log seems to have added a ( in the middle. I have tried this without the (www\.) but that doesn't seem to help.
Reviewing your application, the following simplified code should work. Since your subdomain-subdirectorie names are made unique by prepending "subs", you probably won't need the fancy anti-recursion code I cited. I'm also not sure you need to check for "exists as directory" or "exists as symlink". So try the simplified version first, and then add one or both of those checks back in only if needed.
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} .
RewriteCond %{REQUEST_URI} !^/subs/
RewriteCond %{HTTP_HOST} !^(www\.)?mydomain\.info [NC]
RewriteCond /path/to/public_html/subs/%1.php -f
RewriteRule .* /subs/%1.php [L]
RewriteCond %{HTTP_HOST}!^(www\.)?mydomain\.info$ [NC]
presumably the! means there is no backreference generated in this rule. However with
RewriteCond %{HTTP_HOST} ^(www\.)?([^.]+).mydomain\.info$ [NC]
is there a backreference associated with the (www\.)? part?
I can't work out what number to use in my backreference to pick up the subdomain name.
This means, "If the HTTP_HOST is NOT www.mydomain.info or mydomain.info, upper, lower, or mixed-case, and does not include the optional port number, then the following RewriteRule applies."
"!" means NOT when it precedes regular expressions in mod-rewrite. Backreferences are created any time parentheses are used. Only the backreferences in the last-matched RewriteCond will be available to RewriteRule; if you use and back-reference multiple RewriteConds, their order can be critical. In the example you show, %1 will contain "www." or blank, and %2 will contain the subdomain name.
Some browsers and other user-agents will append a port number to the HTTP_HOST variable, and your rule will fail in that case. I suggest you omit the end-anchor from the pattern above, and just use:
RewriteCond %{HTTP_HOST} !^(www\.)?mydomain\.info [NC]
This will allow a port number to be appended with no ill effect.
These issues are well-covered in the documentation cited in our forum charter [webmasterworld.com].
Jim
I have read the docs, some several times but its easy to miss details like the last rewrite cond matched thing.
so now I'm thinking I should put the subdomain extraction in to the rewriterule so it goes
RewriteRule ^(www\.)?([^.]+)\.mydomain\.info /subs/$2.php [L]
Then I can do whatever tests I like in the rewriteconds and backreference $2 for my subdomain name.
The other question I have is whether I need to use rewritebase to prevent the subdomain being reinjected into the URL after the rewrite is completed.
You don't have that choice, unfortunately. The subdomain is not directly available to RewriteRule, that's why we use RewriteCond %{HTTP_HOST} to access it.
Mod_rewrite can be seen as a very powerful, very precise, but small "language." Therefore there are few right ways to do things, and many wrong ways. Once you get used to "the rules," it's fairly easy to use, because regular expressions and mod_rewrite are both compact-but-powerful "languages" and can be fully learned in a few months.
I should also note that both share another characteristic: They are both far easier to write than to read. This is one reason they are not easy to learn.
I'm afraid it takes some dedication to sit down and read through the documentation of "API phases," "RewriteCond," and "RewriteRule" thoroughly and carefully -- and several times, and then make reference to those sections while working. After a few months, you won't have to look stuff up. However, when I want something to work the first time, I usually look it up and check it anyway.
If you run into a brick wall with RewriteCond back-reference order, remember that you can use multiple RewriteRules in sequence to do a rewrite step-by-step, and you can also create and reference server variables using mod_rewrite, allowing you to create extremely complex rules.
See RewriteRule...[E=Var:Val] and RewriteCond %{ENV:Var}
Let's see what the log file says about the most recent 500 error. In the meantime, don't add further complexity until that problem is resolved.
Jim
The specific confusion about backreferences has arisen as I have seen quite a few rewrite rules which appear to backreference the same variable in a sequence of rewrite conds. I can't find any reference to this in the rewrite mod documentation which as you point out says you can only backreference the last matched condition.
Does this work or not? If I backreference a pattern in one rewritecond is it available to the next rewritecond?
I'm currently trying to get around the backreferencing problem with a repeat of an earlier condition just before the rewrite rule.
Still gives me 500 errors when I test it.
my rewrite code currently is
RewriteEngine On
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST}!^(www\.)?mydomain\.info [NC]
RewriteCond %{REQUEST_URI}!^/subs/
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.mydomain [NC]
RewriteCond /path/to/public_html/subs/%2.php -f
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.mydomain [NC]
RewriteRule ^rewriteme(.*)$ /teachers/%2.php [L]
I stuck rewriteme into the rewrite rule to try to simplify things. As I understand it the whole rewrite thing should fail on the first condition unless I have rewriteme in the request. However I still get a 500 error just from requesting www.mydomain.info.
Once again, we need to wait for the logs.
Just double-checking here, but do you have the required space after each "}" in the RewriteConds? Posting code on this board removes spaces preceding "!" and always leaves this question open.
Do you have access to another host where you could test this code without having to e-mail them for a copy of your log files? This is a rather serious handicap to deal with, and it's hard for me to believe you can work without access to your own log files!
Jim
[b]Options +FollowSymLinks[/b]
RewriteEngine On
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} [b]![/b]^(www\.)?mydomain\.info [NC]
RewriteCond %{REQUEST_URI} [b]![/b]^/subs/
RewriteCond %{HTTP_HOST} ^(www\.)?([b][^.][/b]+)\.mydomain [NC]
RewriteCond /path/to/public_html/subs/%2.php -f
RewriteCond %{HTTP_HOST} ^(www\.)?([b][^.][/b]+)\.mydomain [NC]
RewriteRule ^rewriteme(.*)$ /[b]subs[/b]/%2.php [L]
Posting on this board removes spaces preceding any "!"; make sure you correct those deletions where they occur. You can work around this problem when posting on this forum by using two spaces or by preceding the "!" with a bold-unbold tag pair. I have done so in all the eaxmples I posted.
Jim