mod_rewrite outside of public_html?!? & dir hiding

lostcommander

Member
Messages
52
Reaction score
0
Points
6
I am trying to hide a directory using mod_rewrite such that:
visitor asks for mysite.tld/dir/anyfile.ext
visitor gets redirected to mysite.tld/anyfile.ext

I tried to do this through .htaccess and mod_rewrite using:
RewriteRule ^dir/{1}(.*)$ $1 [R]

Unfortunately, what this is doing is:
visitor asks for mysite.tld/dir/anyfile.ext
visitor gets redirected to mysite.tld/home/user/public_html/anyfile.ext

... WTH?!? :nuts:
Thank you very much. Any help is appreciated.

P.S. I have already done my best to read through all of:
http://www.yourhtmlsource.com/sitemanagement/urlrewriting.html
http://www.sitepoint.com/article/guide-url-rewriting/2/
http://www.workingwith.me.uk/articles/scripting/mod_rewrite
http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

I've also done a few searches for relevant threads in this forum already. So I'm afraid that much more reading is just going to make my eyes bug out.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Make the new URI absolute by adding a leading '/'.
Code:
RewriteRule ^dir/(.*)$ /$1 [R]
Also, the {1} is unnecessary. It causes the previous atom to match just once, which is the default behavior.

As for what's going on, the RewriteBase documentation has some hints.
 
Last edited:

daman371

New Member
Messages
130
Reaction score
0
Points
0
Make the new URI absolute by adding a leading '/'.
Code:
RewriteRule ^dir/(.*)$ /$1 [R]
Also, the {1} is unnecessary. It causes the previous atom to match just once, which is the default behavior.

As for what's going on, the RewriteBase documentation has some hints.

Yep I always use RewriteBase. I was also wondering why the {1} looked strange.
 

lostcommander

Member
Messages
52
Reaction score
0
Points
6
Thank you very much. The RewriteBase thing just went straight over my head the first time(s) I read it. Now that I have an example of exactly what happens when you DON'T use it, it's use is very clear!

I still need some access to the directory I hid, I just don't want any visitors to see the directory. As such, I tried:
RewriteBase /
RewriteRule ^dir/(.*)$ /$1 [R]
RewriteRule ^/(.*)$ dir/$1 [L]

The first two lines act as I would now expect. The last does not seem to get executed though? i.e.
visitor asks for mysite.tld/dir/index.html
visitor is redirected to mysite.tld/index.html
vistor is served mysite.tld/index.html instead of mysite.tld/dir/index.html
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Patterns starting with '/' don't match when RewriteBase ends with a '/'. Use '^/?' rather than '^/'. Also, your rules undo each other, so they won't do what you want. There are better ways of preventing directory indexing. Do one of:
  • turn off auto-indexing for the folder by creating its own '.htaccess' with a Options -Indexes directive.
  • set the directory permissions to 0711 (be sure to read the linked tutorial to understand why).
  • create a default index (file named 'index.html') in the directory
Also, try searching the forums. This question has been answered before.
 
Last edited:

lostcommander

Member
Messages
52
Reaction score
0
Points
6
I am not trying to prevent directory indexing. I am trying to hide the directory name from visitors.

I would like to be using a CMS. I would like to be able to change which CMS I am using, so I would like the entire CMS to reside in its own folder, spread out into the base directory. I would like the CMS to look as though it is the primary part of the site.

e.g. Vistor asks for www.mysite.tld/
Visitor gets www.mysite.tld/cms/index.php and URL does not reveal this
That should be doable with .htaccess by simply omitting the [R] flag, correct?

I would also like to hide all relative sub-links, such that:
visitor clicks a link on mysite.tld/cms/index.php pointing to images.php
visitor is served mysite.tld/cms/images.php but the URL is mysite.tld/images.php

In short, I never want to see /cms/ in URLs on my site, but I would like to have that directory in the file structure AND be able to access its contents through an URL.

Also, try searching the forums. This question has been answered before.
I did search the forums and I am NOT trying to make a directory private.

The pattern matching bit and the Options -Indexes are interesting though. I did not know either. Thank you very much for your assistance. I hope I have better described this time what I am attempting to accomplish?
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
I see now. Sorry about the misunderstanding. People keep writing they want to "hide a directory" and mean many things by it. Your explanation is very clear.

It's tricky to do what you're trying with just mod_rewrite, due to the mutually recursive rules. You might want to consider using a subdomain instead.
 

lostcommander

Member
Messages
52
Reaction score
0
Points
6
Darn the English language and it's multiple meanings... lol.

Clearly, from my short experience with this, you are correct that this is tricky. I am really confused as to WHY it is tricky though. I included the [L] "Last" flag on the last rule, so it should make the second change and then STOP, shouldn't it? However, it instead presents my browser with a 302 Found - Error.
RewriteRule ^moola_cms/(.*)$ $1 [R]
RewriteRule ^(.*)$ moola_cms/$1 [L]

I am currently toying with RewriteCond to see if I can make the last rule not trigger more than once. I am having trouble figuring out exactly what %{REQUEST_URI} is though. Obviously, if no rewrite rules have been triggered yet, it is simply the URL starting after .tld/ and if the only rewrite rules that have been triggered have [R] "Redirect", then I would expect those changes to be represented. However, if a rewrite rule without [R] triggers, are it's changes made to %{REQUEST_URI}? The path to the resource the request is asking for has been changed, but the request itself has not, so I would guess that the variable does not change, but I have no way of knowing as I have no way to simply print out the variable's value to view it and find out.
RewriteRule ^moola_cms/(.*)$ $1 [R]
RewriteCond %{REQUEST_URI} !^moola_cms/.*$
RewriteRule ^(.*)$ moola_cms/$1 [L]

I have also tried using RewriteCond using a backreference to the rewrite rule below it. This also throws a 302 Found - Error at me and the link is to the same URL address I began with and either does nothing or returns the same when I click it.
RewriteRule ^moola_cms/(.*)$ $1 [R]
RewriteCond $1 !^moola_cms/.*$
RewriteRule ^(.*)$ moola_cms/$1 [L]
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Clearly, from my short experience with this, you are correct that this is tricky. I am really confused as to WHY it is tricky though. I included the [L] "Last" flag on the last rule, so it should make the second change and then STOP, shouldn't it? However, it instead presents my browser with a 302 Found - Error.
The [L] is working just fine. Rewriting stops, the redirect (you probably want a 301, not a 302) is sent to the browser, which requests the new page. The 'moola_cms/' is then prefixed to the URI by the 2nd RewriteRule, as it should. The problem is internal redirects.

Other modules (such as mod_index, which turns a 'foo/' URL into a 'foo/index.php' URL) cause an internal redirect, which causes another round of rewrites. The trick is in preventing rewrite on the internal redirect (or preventing the internal redirect). RewriteRules have an [NS] flag to prevent rewrites on internal sub-request, but that's different from an internal redirect. If you find a way to prevent the internal redirect, you will probably have further problems.

I am currently toying with RewriteCond to see if I can make the last rule not trigger more than once. I am having trouble figuring out exactly what %{REQUEST_URI} is though. Obviously, if no rewrite rules have been triggered yet, it is simply the URL starting after .tld/ and if the only rewrite rules that have been triggered have [R] "Redirect", then I would expect those changes to be represented. However, if a rewrite rule without [R] triggers, are it's changes made to %{REQUEST_URI}?
No. REQUEST_URI is "[t]he resource requested in the HTTP request line", according to the documentation. It is not altered by the rewrite rules.

The path to the resource the request is asking for has been changed, but the request itself has not, so I would guess that the variable does not change, but I have no way of knowing as I have no way to simply print out the variable's value to view it and find out.
You could use a RewriteCond to capture the value of REQUEST_URI and add it to the query string.
Code:
RewriteRule ^/?nonexistent/(.*) /$1
RewriteCond %{REQUEST_URI} (.*)
RewriteRule (.*) $1?olduri=%1 [QSA]
This is untested, but you should be able to request "/nonexistent/echo.php", where "echo.php" echos (at the very least) $_GET.

I have also tried using RewriteCond using a backreference to the rewrite rule below it. This also throws a 302 Found - Error at me and the link is to the same URL address I began with and either does nothing or returns the same when I click it.
Code:
RewriteRule   ^moola_cms/(.*)$    $1    [R]
RewriteCond  $1    !^moola_cms/.*$
RewriteRule   ^(.*)$    moola_cms/$1    [L]
This will still have problems with internal redirects.
 

lostcommander

Member
Messages
52
Reaction score
0
Points
6
Mmm, good info, Mission. I had not even considered the possibility that internal redirects were responsible for .tld => .tld/ => .tld/index.html... That is quite interesting and I may find a use for that at some point. In the mean time...

THANK YOU LADY ANNA!!! That is EXACTLY what I was searching for, but could not find. Even better than finding it of course is learning that IT WORKS! Spectacular. Thank you both very much! :lol:
 

Anna

I am just me
Staff member
Messages
11,752
Reaction score
581
Points
113
glad to be of help. I only knew of it since I messed with it myself the other night, trying to make my folders less cluttered (I have a few subdomains on my account as well)
 
Top