Forum Moderators: phranque

Message Too Old, No Replies

RewriteCond issue

         

gregra

2:06 pm on Jan 16, 2010 (gmt 0)

10+ Year Member



Hi there.
I'm kind of new to the rewrite_mod stuff, so forgive me for my noobiness...

I have a certain http://example.com domain and a website farm there.
Every website is under different folder in the public_html directory, for example - mainsite,site1,site2,site3 etc so that I have http://example.com/mainsite, http://example.com/site1,http://example.com/site2, http://example.com/site3 etc.

I'm trying to to put a rewrite rule that will work only for a certain condition. I need that when someone goes into http://example.com, he be redirected into the http://example.com/mainsite (that's easy, I did it with a simple index.php inside the root directory) but will not have a long URL such as http://example.com/mainsite/index.php?title=My_Page but a short and nice one such as http://example.com/My_Page. I was able to achieve that with these conditions:


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)?$ /mainsite/index.php?title=$1 [L,QSA]

My problem is that I want that users will be also able to get into the other sites through http://example.com/site1, http://example.com/site2 etc so that the above rule will not apply.

Any ideas?

Greg

jdMorgan

2:48 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You can more than double the speed of that code simply by adding some exclusions, and integrate your new requirement as well. Assuming that your code goes in example.com/.htaccess:

RewriteCond $1 !^(site1¦site2¦site3¦site4)(/.*)?$
RewriteCond $1 !(^mainsite/index\.php¦\.(gif¦jpe?g¦css¦js¦png¦ico)¦^robots\.txt¦^sitemap\.xml)$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ mainsite/index.php?title=$1 [QSA,L]

The exclusion of /mainsite/index.php itself saves two filesystem checks for every request to your server. As the server may actually have to go check the physical disk for some or all of these filesystem checks, making this simple exclusion can often have dramatic effects on the speed of your site.

Excluding images, css, javascripts files, robots.txt, and sitemap.xml further reduces the number of disk-checks, and can lead to an equivalently-dramatic speed-up if your site design supports doing so.

For best results, order the excluded URL-paths and filetypes as shown, with "index.php" first, followed by the other URL-paths and filetypes according to how frequently they are requested from your server. See your mainsite server 'stats' for the information required to tune this ordering.

Instead of "publishing" all of these "/mainsite", "/site1" and "/site2" subdirectories in your URLs, I'd suggest you look into using subdomains. For scalability, this will require that your server have a unique IP address, but will allow you to use example.com, site1.example.com, site2.example.com, site3.example.com, etc., and map those to the "/mainsite", "/site1", "/site2", and "/site3" subdirectories respectively -- without publishing the subdirectory-filepaths in your URLs. The impression that these are somewhat-separate sites will then be signaled much more strongly to both users and search engines.

Important: Replace all broken pipe "¦" characters above with solid pipes before use; Posting on this forum modifies the pipe characters.

Jim

gregra

3:40 pm on Jan 16, 2010 (gmt 0)

10+ Year Member



Jim,
Thanks for the quick reply!
But I think I didn't explain myself well enough.
My configuration is a little more complicated than what I described.

I'm trying to build a wiki-farm, so that whenever I like, I can add a new "farm" (that means a new instance of my MediaWiki installation). The neat trick is that I'm doing it with only one source of MediaWiki files, that means that every instance of a wiki I have is using the same source code (the only difference is the URI, the local settings and the DB).
So, all the source files are located in just one "wiki" directory and all my wiki sites (site1,site2 etc) are not really located under public_html but instead are all "dummy" names (script path parameters) that distinguish between each instance of the wiki (so site1 has the URL http://example.com/site1 and has script path = site1) but what I actually do is a rewrite in the .htaccess from the dummy script path to the actual one - /wiki/, so it looks like this:


RewriteRule ^site1/(.*)$ /wiki/index.php?title=$1 [PT,L,QSA]
RewriteRule ^site1/(.*)$ /wiki/$1 [PT,L,QSA]

and this rule is applied in the .htaccess file for every wiki instance.
So far so good (not best, but it's the best I can do...)

Now, I want that my main wiki will have an even shorter URL - http://example.com/Some_Page and not like on all other wikis - http://example.com/site1/Some_Page, http://example.com/site1/Some_Page and so on.
So for this I have:


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)?$ /wiki/index.php?title=$1 [L,QSA]

So, my problem is that I can't achieve both conditions. I want that when someone hits http://example.com they go to my main wiki site (but that the URL will remain http://example.com/Some_Page) and when he goes to http://example.com/site1 than he will be (and stay there) for any URL that he hits on that site.
That is why I asked if there is some condition for the first part (only for the main wiki) so only when he hits http://example.com or http://example.com/Some_Page or http://example.com/wiki/index.php?title=Some_Page the rule


RewriteRule ^(.*)?$ /wiki/index.php?title=$1 [L,QSA]

will work, and for all other URLs it won't work and only the second set of rules will work:

RewriteRule ^site1/(.*)$ /wiki/index.php?title=$1 [PT,L,QSA]
RewriteRule ^site1/(.*)$ /wiki/$1 [PT,L,QSA]

Sorry for the long post, hope that I've managed to get through the gist of it.

Greg

jdMorgan

6:17 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm not sure what the question is, then, because I modified the rule you posted to do just that -- except for the "wiki" path-part which I presume you can use to replace (site1¦site2¦site3...) in the first RewriteCond and add to the path shown in the rewriterule substitution...

Your "second set" of rules likely won't work properly anyway, since the RewriteRule patterns are identical and therefore, only the first of the two rules will actually do anything. And note that [QSA] is meaningless on the second rule, and [PT] likely isn't required on either rule unless you're passing these requests to an application server or to another Apache module.

If the "wiki path" changes outlined above don't help or if you cannot apply them, I'd suggest you review your actual requirements, and try to distill them into a succinct but comprehensive description. It would be better to think through and decide on every aspect of your plan before rushing into implementation, and it would be a much better use of the 'resources' volunteered in this forum.

Jim

gregra

7:30 pm on Jan 16, 2010 (gmt 0)

10+ Year Member



OK, thanks.
I think I got it.
Another question:
How can I add a rewrite rule with a parameter, so that someone that goes to http://example.com/site1 will be redirected to site1 URI and so on (because I don't want to add a new rule for every site that I add).
So I guess the rule should be with a %{REQUEST_URI} condition.

Will appreciate the help...

Greg

jdMorgan

10:31 pm on Jan 16, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> So I guess the rule should be with a %{REQUEST_URI} condition.

These are useful almost exclusively for *negative-match* conditions; If you want the positive-match condition, that's already built-in to RewriteRule, because that is what the RewriteRule pattern matches. So therefore a RewriteCond testing the REQUEST_URI for a positive match is fairly-rarely used.

I don't understand your question directly above, specifically, "redirected to site1 URI and so on". Concrete examples of several different client-requested URLs and their desired dispositions (whether by an external redirect to a different URL or an internal rewrite to a non-default server filepath) would add clarity.

Jim

gregra

8:00 am on Jan 17, 2010 (gmt 0)

10+ Year Member



Jim, you are a real asset to this forum and good man!
These are my examples:
1) User hits http://example.com/site1. He should be redirected by the next rewrite rule:
 
RewriteRule ^site1/(.*)$ /wiki/$1 [PT,L,QSA]

2) Another user hits http://example.com/site2 and should also be redirected by a similar rule:
 
RewriteRule ^site2/(.*)$ /wiki/$1 [PT,L,QSA]

And so on and so forth.
There could be hundreds of these users that sign up to my site and get their own URL - http://example.com/site1,http://example.com/site2, http://example.com/site3 etc.
I don't want to add for every new user the rule:

 
RewriteRule ^"your_URI"/(.*)$ /wiki/$1 [PT,L,QSA]

I want the rewrite rule to do this automatically so I thought that maybe the condition
 
RewriteRule %{REQUEST_URI}/(.*)$ /wiki/$1 [PT,L,QSA]

could do the trick, but it's not working...

Greg

g1smd

8:30 am on Jan 17, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



1) User hits http://example.com/site1. He should be redirected by the next rewrite rule:

The problem here is terminology. You ask about a "redirect" and then show code for a "rewrite". If someone is "redirected", their browser makes a new request for a new URL and the URL shown in the browser URL bar changes. That is not what you require at all.

Next, you need for the original URL request to contain some reference to "site1" in order to distinguish that it is a request for "site1" and not a request for "site2". Whether you do that as 'example.com/site1' or as 'site1.example.com' or as 'site1.com' is merely a matter of choice.

gregra

8:56 am on Jan 17, 2010 (gmt 0)

10+ Year Member



You right, I meant a rewrite of course and not a redirect...

The original URL contains this reference. It's in the back-end of my Mediawiki. When the user hits http://example.com/site1 the scripts are loaded from the real /wiki/ folder but the specific settings (like DB name) are loaded from different Settings.php file. So I need that when the user hits one of these URLs http://example.com/{his specific site}, the request will rewrite to according to the rule:


RewriteRule ^"your_URI"/(.*)$ /wiki/$1

Greg

jdMorgan

9:32 pm on Jan 18, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Again, I'd suggest the subdomain approach, as any request for a subdomain not equal to "www" could be presumed to be a "user" subdomain request, and therefore easily be rewritten to a subdirectory.

If you want the username in the actual URL-path as opposed to the subdomain, then *some* method of looking at the URL and easily determining that it is a 'user' request is required. You can either do it explicitly, requiring you to keep and maintain a list of all of the usernames in one or more rewriterules, or you can do an end-run around most of the problem by simply defining your 'user' subdirectories to all reside under one directory, or to have a shared and distinct prefix. IOW, put all 'sites' under, /sites/site1, /sites/site2, /sites/site3, or name their URLs /sites-site1/, /sites-site2/, /sites-site3/, etc.

Then you can simply match the prefix-path and if it's "/sites" the rule can rewrite without causing interference with other subdirectories belonging to your main site, and without requiring you to explicitly list all the "sites."

Jim

gregra

7:18 am on Jan 19, 2010 (gmt 0)

10+ Year Member



Jim, thank you very much.
I will really appreciate if you will show me the exact rule that does what you've described.

Greg

g1smd

10:12 am on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Let's see your attempt and we'll help you fix it, as the purpose of this forum is your education. There's not enough volunteers to crank out code 'help-desk' style.

gregra

10:58 am on Jan 19, 2010 (gmt 0)

10+ Year Member



Tried this:

RewriteCond %{REQUEST_URI} !^/sites/.*
RewriteRule ^/sites/%{REQUEST_URI} %{REQUEST_URI}/

But it doesn't seem to do the trick...

Greg

jdMorgan

3:46 pm on Jan 19, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Simplify:

RewriteCond $1 !^sites/
RewriteRule ^(.*)$ /sites/$1 [L]

Then expand:

# if not already rewritten to '/sites/'
RewriteCond $1 !^sites/
# and if requested 'site name' exists as a directory under '/sites/'
RewriteCond %{DOCUMENT_ROOT}/sites/$2 -d
# then rewrite the request to the '/sites' subdirectory
RewriteRule ^((([^/]+/)+).*)$ /sites/$1 [L]

Be sure to completely flush (delete) your browser cache after making any changes to server-side code.

Jim

gregra

6:09 pm on Jan 19, 2010 (gmt 0)

10+ Year Member



Many thanks Jim!