Welcome to WebmasterWorld Guest from 54.80.93.19

Forum Moderators: Ocean10000 & phranque

Tweak directive in htaccess file

Correct a RewriteRule directive in htaccess file to fit the bill

     
3:17 pm on Aug 6, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


I want to map the name of an actual folder to a dummy folder name used in php / html, using htaccess file.

So on the server I have this real folder called 'mydata' which contains many php files and subfolders.

When I retrieve data from this folder, in php or html files, I want to write the path as 'somedata', instead of 'mydata'; for example: /somedata/mydatafile.php instead of /mydata/mydatafile.php. So the 'mydata' folder name will be always hidden from users for security reasons. 'somedata' is just a name, there isn't an actual folder on the server.

I have a few addon domains beside the main domain, and the same mydata folder exists on each add-on domain too. The structure in cPanel is:

'/public_html/mysite.com/mydata'
'/mysite2.com/mydata'
'/mysite3.com/mydata'

where mysite.com is the main domain and the others are addons.

The htaccess file should map 'somedata' folder name to 'mydata' folder name, in any path in any domain and addon-domain, so I would place it in the root (is root considered where public_html, mysite2.com and mysite3.com sites are?) I prefer to do it without redirect, the simplest way possible for the server.

With RewriteEngine On, I tried the following:

1.
Alias /somedata /mydata

2.
RewriteRule ^mydata/(.*)$ /somedata/$1 [NC,L]

3.
RewriteCond %{REQUEST_URI} ^/somedata
RewriteRule .* /mydata/ [NC,L]


I'm stuck because of the syntax, can we make at least one work...?
4:29 pm on Aug 6, 2018 (gmt 0)

Administrator from US 

WebmasterWorld Administrator not2easy is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Dec 27, 2006
posts:3902
votes: 222


You want to replace (mydata) in the request to (somedata) and capture the rest of the request to append it. I'd leave off the [NC] unless the public is expected to type in these requests.

This is not something I'm doing myself so my example is not 100% certain, but it may help as a starting point:
RewriteRule ^(somedata)$ $1/ [R]
RewriteRule ^(somedata)/(.*)(\.[a-z]+)$ /mydata/$1 [L]

The "(\.[a-z]+)" part can be (\.html|php) if those are the only extensions used in /mydata/ files.

Note that it is a 302 (temporary) redirect and you may want to disallow /somedata URLs for bots.

BUT - I seem to recall that there is some additional code because the request is a 'virtual' directory that doesn't actually exist. I assure you that Someone Who Knows can be more helpful here.
8:48 pm on Aug 6, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


I prefer to do it without redirect
If you want to keep the “real” filename and/or directory hidden, you have to do it without redirecting.

Do you want everything to be served from the same physical directory, regardless of which domain the original request uses? Or does each domain have its own directory, which just happens to have the same name each time?

I've got a pretty strong feeling RewriteRules in htaccess won't let you go above the current domain's root. It can certainly be done in php-or-similar, though: any language that lets you specify the full physical filepath.

The Alias directive can definitely not be used in htaccess. (If the docs are correct, 2.4 lets you use it in <Directory> sections, while 2.2 was limited to config and vhost.) Besides, mod_alias typically executes after mod_rewrite, so it's a bit iffy all around.
12:03 pm on Aug 7, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


not2easy - thanks. I think there is a confusion because you say "want to replace (mydata) in the request to (somedata)"
Please read the post again, it's more like the other way round...
In the request (code in php and html files) it is 'somedata' which is a fictitious file name and this one should be replaced with 'mydata' which is a real folder on disk.
12:09 pm on Aug 7, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


lucy24 - thanks, as I showed the structure in the post, there is a 'mydata' folder in each site (domain).
So, seen from htaccess file, the path is different in each case.

htaccess doesn't allow access above the current domain's root, but if I place the htaccess file in the root, I can see all domains from there, so no need go above.
From root I can see this:
/public_html/mysite.com/mydata
/mysite2.com/mydata
/mysite3.com/mydata

So if Alias can't be used, which version should I use?
Thanks
5:59 pm on Aug 7, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


Back to the original two options ...
RewriteRule ^mydata/(.*)$ /somedata/$1 [NC,L]

RewriteCond %{REQUEST_URI} ^/somedata
RewriteRule .* /mydata/ [NC,L]
The second version will always be wrong, no matter what you're trying to do. With very, very rare exceptions, a (positive) REQUEST_URI condition belongs in the body of the rule, so the server doesn't have to evaluate conditions on every request ever. As it stands, all requests for anything in /somedata will be rewritten to /mydata/ and-that's-all--and you did say, didn't you, that /mydata/ contains lots of files and folders. Is it possible you've got mod_rewrite syntax mixed up with mod_alias syntax? In mod_rewrite you always have to capture; nothing gets reappended by default.

Beyond that: the two quoted rules have the exact opposite effect. One of them rewrites requests for /mydata/ to serve content from /somedata/; the other rewrites requests for /somedata/ to serve content from /mydata/.

From root I can see this:
What does “see” mean? The problem is not with the pattern but with the target. When RewriteRules are used in any directory context--whether a <Directory> section of config or an htaccess file--the target is treated as a URI, meaning that the first / is the root of the current domain. But what does that mean if there are two domains involved: the one being requested, and the one whose directory the rule is located in?

Answer: I have no idea. Normally at this point I would go to my test site and do some experimenting. Nothing beats direct observation. But my host doesn't use the primary/addon directory structure, so there's no way to test. You may need to do some experimenting of your own. Create a file with some unique name, and put it in one of your subdomains' /mydata/ folders. Make another one, with a different name, and put it in the primary domain's /mydata/ folder. Request the assorted files in your browser, and see what you get. You may need to look at both sites' error logs for “file not found” lines. (In error logs, File Not Found will show up even in situations where the user doesn't see a 404.)

Which brings us to: Are all your RewriteRules located in the root (“primary” domain)? What do you do with rules that are only intended for one of the addons? Is there a HTTP_HOST condition each and every time?
11:29 am on Aug 8, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


Thanks, there aren't any HTTP_HOST conditions.

I mentioned what the actual directory structure is to point out that it's different from a structure like:
/public_html/mysite.com/mydata
/public_html/mysite2.com/mydata
/public_html/mysite3.com/mydata

so I think the root is one level up of the public_html.
From the root, public_html, mysite2.com and mysite3.com appear as subfolders.

Anyway, could the first rule be re-written something like this, to fit the bill?

RewriteRule ^(.*)/somedata/(.*)$ $1/mydata/$2 [NC,L]
2:57 pm on Aug 8, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


So now the code is just this:

RewriteEngine on
RewriteRule ^(.*)/somedata/(.*)$ $1/mydata/$2 [NC,L]

I use the same code in each of the sites to get the header for example:
$path = $_SERVER['DOCUMENT_ROOT'];
include ($path . '/somefolder/header.php');

I tried with .htaccess file both in root and in individual sites.
When I place it in the root of a site, say mysite2.com, if I echo the above path, I get:
/home/userid/mysite2.com/somefolder/header.php
instead of
/home/userid/mysite2.com/myfolder/header.php

and same result if I place it one level higher, in the root.

(Or, when I use 'echo' in a php file it is correct that htaccess directives don't apply and this ...?)
5:40 pm on Aug 8, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


^(.*)/somedata/(.*)$
Never use .* or .+ at the beginning of a pattern if there is any conceivable way out of it. The server will capture all the way to the end of the string--and will then have to backtrack when it sees “Oh, oops, there has to be a /somedata/ after it”. (A server evaluating a Regular Expression basically operates in one dimension.) But the whole question is about to become moot, because ...

echo
Tralala, we can sidestep the whole problem. You don't need to say anything in htaccess at all; shift it to php. Within the php you can use either the DOCUMENT_ROOT approach--if you want things to be handled differently for each site--or the /full/literal/filepath/ approach--if you want all content served from the same place. Which one you use depends entirely on the requirements of the sites. To some extent you can combine the two, say if all sites use the same underlying code but then pull in site-specific data.

Or, when I use 'echo' in a php file it is correct that htaccess directives don't apply and this ...?
htaccess doesn't touch php requests* ... but your htaccess may determine which exact php file is handling the request in the first place.

At this point I suggest you mosey on over to the php subforum if you need help formulating the rules in all those individual php files. I speak about three words of php, and we have now used them up.


* Sort of. In rare cases, such as auto-indexing, htaccess can “see” an internal php request. But that doesn't apply here.
2:39 pm on Aug 9, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


OK, thank you for the good advice.
And still... I don't understand why the code

RewriteEngine on
RewriteRule ^/somedata/(.*)$ /mydata/$1 [NC,L]

doesn't work, when it actually should...
4:50 pm on Aug 9, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


Oh, oops, I overlooked that. In a directory context--whether htaccess or a <Directory> section in config--the form
^/blahblah
will always fail, because everything up to the directory slash is disregarded. Start with the bare directory name, no slash.
6:40 pm on Aug 9, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


OK, thanks. So I've just tried with

RewriteEngine on
RewriteRule ^somedata/(.*)$ mydata/$1 [NC,L]

and still not working... am I missing something..?
7:18 pm on Aug 9, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


Before anything else, put a / at the front of the target. (This is a security precaution against evil hackers who come in with plans of All Your RewriteBase Are Belong To Us; it should have no effect on the rule's operation unless there is already a non-standard RewriteBase directive in place.)

Now then. Diagnostics time:

What happens when you manually request
example.com/somedata/blahblah
? “Manually request” means type it in your browser’s address bar. Of course no human will really do this--but your server doesn’t know that. To the server, all requests are the same. Use the literal text “blahblah”, or “foobar” or any old nonsense--anything that you know doesn’t exist in the relevant directories.

Now consult your site's error logs to see what file is being requested internally. The visible 404 response will not tell you anything; you have to look at the error logs. (If you don’t get a 404--that’s a problem.) Compare what happens in the primary site and in any addon site.
2:35 pm on Aug 13, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


Thanks, I just did so. First, I put the / in front of target.

Then, in browser address bar I requested manually the file:
mysite.com/somefolder/header/index.php
(the index.php file is real and it exists on the server)

The result of the request is that the server returned the ouput of the file:
mysite.com/myfolder/header/index.php
The fictious name 'somefolder' was replaced to the real one, 'myfolder'

So from this I can understand that the script works correctly!
So there is no error output.

But now when I request
mysite.com/index.php
the page doesn't display correctly at all.

The index.php page includes a number of scripts from 'myfolder',
which I try to retrieve with scripts like:
$path = $_SERVER['DOCUMENT_ROOT'];
include ($path . '/somefolder/header/index.php');

but in this case none of the external php files are retrieved correctly; the httaccess directive doesn't seem to work...

(Of course if the including scripts change to:
$path = $_SERVER['DOCUMENT_ROOT'];
include ($path . '/myfolder/header/index.php');
then the index.php page is displayed correctly. )

So what can I do to apply htaccess directives to the php files included this way in other php files?
3:54 pm on Aug 13, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


So what can I do to apply htaccess directives to the php files included this way in other php files?
Whoa there. You’re mixing two different things. htaccess deals with external requests received by the server (and also with certain types of internal requests generated by some apache mods). php deals with, well, php. If /somefolder/ doesn’t physically exist, you can’t invoke it in php. You have to use its real, physical name.
10:04 pm on Aug 13, 2018 (gmt 0)

Administrator

WebmasterWorld Administrator phranque is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Aug 10, 2004
posts:11392
votes: 157


The index.php page includes a number of scripts from 'myfolder',
which I try to retrieve with scripts like:
$path = $_SERVER['DOCUMENT_ROOT'];
include ($path . '/somefolder/header/index.php');

but in this case none of the external php files are retrieved correctly; the httaccess directive doesn't seem to work...

if you are including a filepath you aren't making a web request, so .htaccess isn't involved.

however if you make a web request by specifying an appropriate HTTP url such as http://localhost/somefolder/header/index.php it may work as you wish.
it may require some configuration changes to work.

you might want to read this php manual page:
Using remote files [secure.php.net]

you should carefully consider whether you really want to make an external (web vs file) request as this will likely slow your script execution.
8:07 am on Aug 14, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


if you are including a filepath you aren't making a web request, so .htaccess isn't involved.

Oh, this is where my confusion comes from. I though that calling a php file from wherever, no matter what the calling method is, that is a http request... ('cause otherwise how does the server know to parse the script in that file and serve the result....?) So from server's point of view, what kind of request is it, if not http.

Actually, I don't want to replace the current code with external requests.

But if this approach doesn't work is there a way to hide the folder with important scripts, better than the already mentioned code:
$path = $_SERVER['DOCUMENT_ROOT'];
include ($path . '/myfolder/header/index.php');

Thanks.
5:51 pm on Aug 14, 2018 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lucy24 is a WebmasterWorld Top Contributor of All Time 5+ Year Member Top Contributors Of The Month

joined:Apr 9, 2011
posts:15019
votes: 665


If the file is only invoked by php, then it is already hidden. Make a folder with a non-predictable name, and don't use it for anything except internal php business.

If I had it to do over again, I would have given my /includes/ directory a different name for this very reason.
5:58 am on Aug 15, 2018 (gmt 0)

New User

10+ Year Member

joined:Sept 20, 2004
posts: 21
votes: 0


OK, clear now. Your guidance was very helpful for me.
Thanks a lot.
 

Join The Conversation

Moderators and Top Contributors

Hot Threads This Week

Featured Threads

Free SEO Tools

Hire Expert Members