0

I'm new to the whole apache configuration and I have a problem to which I can't seem to find a solution on google.

In short I can't hide folders from URL because it looks as if the document root character (^) starts at the beginning my XAMPP installation folder - /opt/lampp/htdocs/batulabe/

Detailed I've installed a fresh XAMPP VM on my mac without configuring much so everything is basically default. This is the current folder layout for the website:

-batulabe (the document root I intend to make, this folder is inside htdocs)
--public
---pages
----*php pages
--private
---*private, inaccessible files

I'm trying to rewrite URL's like:

http://localhost/batulabe/public/pages/varpage.php

to

http://localhost/batulabe/varpage

result I am getting

http://my_ipv4_address/opt/lampp/htdocs/batulabe/public/pages/public/pages/account.php.php

I have created an extra .conf file called website.conf and made Apache read it by writing one line that looks like this - Include "/opt/lampp/apache2/conf/website.conf". Other than that, these are the only files (.conf) that I've changed:

-httpd.conf

Alias /bitnami/ "/opt/lampp/apache2/htdocs/"
Alias /bitnami "/opt/lampp/apache2/htdocs"

<Directory "/opt/lampp/apache2/htdocs">
    Options Indexes FollowSymLinks
    LoadModule rewrite_module modules/mod_rewrite.so
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

-website.conf (the same extra configuration file I made for Apache to read)

<Directory "/opt/lampp/htdocs/batulabe">
  Options -Indexes
  Require all granted
  ErrorDocument 403 /batulabe/index.php

</Directory>

<Directory "/opt/lampp/htdocs/batulabe/private">
  <LimitExcept POST>
    Require all denied
  </LimitExcept>
</Directory>

To save time on restarting Apache, my rewrites are temporarily written in .htaccess (it is stored in "/batulabe" the website root folder). Inside looks like so:

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} -f
        RewriteRule ^(.*)$ public/pages/$1.php [R=301,L]
</IfModule>

The flag [R=301] helped me to see why (probably?) none of the previous rewrite combinations have worked so far, which is because ^ results in http://my_ipv4_address/opt/lampp/htdocs/batulabe/ instead of http://my_ipv4_address/batulabe/ or at the very least without the website folder "/batulabe" since everything is default from installation.

Any help is greatly appreciated!

Alex
  • 39
  • 5

1 Answers1

0

Why do you implement an external redirection using the R=301 flag? That is not what you want, you want an internal rewrite instead. So remove that flag!

Also the RewriteCond does not really make sense. You test if the requested path points to a physical file in your file system. But that most likely is not the case considering that you want to rewrite the requests to some other folder. Instead you would have to check if the rewritten path points to a file.

In the code snippets you posted there are some discrepancies towards where your actual DOCUMENT_ROOT folder is defined in your configuration. Your are using different paths in different files: /opt/lampp/apache2/, /opt/lampp/apache2/htdocs/, /opt/lampp/htdocs/ ... Fix that. It is only one of those.

And last not least you should place that distributed configuration file (".htaccess") in the actual DOCUMENT_ROOT folder of the http host. Please check that in your configuration. Reason is that you want to move the rule into the http server's host configuration later on (which is what I understand from your phrasing "my rewrites are temporarily written" ...

This is an approach that should point you into the right direction:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/batulabe/public/pages/
RewriteRule ^/?batulabe/(.*)$ /batulabe/public/pages/$1.php [L]

In general you should prefer to place such rules in the actual http server's host configuration instead of using distributed configuration files. One of the reasons is to avoid added complexity and confusion over the different handling of paths.

It certainly is possible to implement rules in a configuration file stored inside a folder further down the hierarchy as you did. That should work:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/public/pages/
RewriteRule ^(.*)$ public/pages/$1.php [END]

But note that you'd have to change those rules again when moving them to the central configuration. Also you risk more unexpected interactions with other rules you implemented somewhere in the hierarchy. Which is why one should generally avoid such scheme in my experience.

arkascha
  • 41,620
  • 7
  • 58
  • 90
  • Thanks for a detailed reply, however, I get a 404 error. Tried both of your examples and since the main configuration file inside ```opt/lampp/etc/httpd.conf``` still has the default ```DocumentRoot "/opt/lampp/htdocs"```, your ```^/?batulabe/(.*)$ /batulabe/public/pages/$1.php [L]``` was supposed to work (from what I understand) but I get the said error and writing a full URL with ```/public/pages/account.php``` still works? Why? The other example as I though didn't work and lead to an 500 error (I mainly tried it anyway for _what if_). All still written inside .htaccess not website.conf – Alex Oct 31 '22 at 01:42
  • That contradicts what you write in the question ... `/public/pages/account.php` and `/batulabe/public/pages/account.php` are two very different things ... – arkascha Oct 31 '22 at 07:39
  • About the http status 500: that most likely is an endless rewriting loop. Always check your http server's error log file in such cases, that is where you can simply _read_ what causes the issue instead of having to _guess_ . Indeed I forgot the conditions to break such rewriting loops yesterday. My apologies. I added them to the answer. – arkascha Oct 31 '22 at 07:41
  • All good I appreciate you bothering in anyway. What I actually meant by full URL is ```http://myipv4/batulabe/public/pages/account.php```. I've tried your 1st edited example though I still get a 404 while that same original full URL still works ('GET /batulabe/account HTTP/1.1" 404 1207' or 'script '/opt/lampp/htdocs/batulabe/account.php' not found or unable to stat' is the error in log). 2nd example still leads to the 500 error ("Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion'"). Is it even possible to hide folders in url? – Alex Oct 31 '22 at 09:13
  • if I write your second example in _website.conf_ with a small addition of ```RewriteBase /``` just after ```RewriteEngine On``` I don't get the 500 err loop but 404 not found instead. (rewrite rule, inside _website.conf_, was written in between the ``````), and that full URL now gives 404. Could it be that I missed some detail in my question? Because right now following the 404 and the logs saying ```batulabe/account not found``` it looks as if I'm asking apache to look for "account" file inside "/batulabe/" instead of just hiding two folders. – Alex Oct 31 '22 at 09:52
  • 'script '/opt/lampp/htdocs/batulabe/account.php' not found is nothing that can result from the lines I suggested. That indicates that you have either other rules in place somewhere or that you are simply looking at client side cached results. – arkascha Oct 31 '22 at 10:01
  • That second observation you write shows that the rules do _not_ get applied. – arkascha Oct 31 '22 at 10:02
  • I tried everything I could (returning back to .htaccess for quicker testing) and still end up with 404 for ```.../batulabe/account``` and working for ```.../batulabe/public/pages/account.php```. Getting real frustrated with these rewrites... at this point it's easier to understand the C++ pointers – Alex Oct 31 '22 at 11:20
  • We have to assume that there is some factor involved that is currently not considered, probably because it is unknown. Please re-check the http server's access log file for what requests are actually coming in _from the point of view of the http server_ ... – arkascha Oct 31 '22 at 11:45
  • The next step will be that you enable rewrite logging. Assuming that you are using a current version 2.4 of the http server that would be the documentation you need to follow: https://httpd.apache.org/docs/current/mod/mod_rewrite.html#logging Rewrite logging allows to understand exactly each step that is performed inside your rewriting engine. – arkascha Oct 31 '22 at 11:47
  • Not sure what version is my current XAMPP VM on but 2.4 log level 3 worked. I can't yet understand what do the logs say, which pov is which and etc. Can I ask if _you_ could let me know what's wrong? [link](to https://justpaste.it/2p0cq) has all of the lines. (currently using your 1st ex.) First three lines are from visiting ```http://my_pv4/batulabe/account``` and the rest were generated after visiting the full URL ```http://my_ipv4/batulabe/public/pages/account.php``` – Alex Oct 31 '22 at 12:32
  • Prior to your last comment, I dug a bit more on google and tried copy pasting straight answers similar to yours. One line finally made my intended url ```http://my_pv4/batulabe/account``` work. It is - ```RewriteRule ^account?$ ./public/pages/account.php [L]``` (I haven't fixed details like dot prefix yet and tested). However full url also works and of course the job is hardcoded and not dynamic but I don't get why this works compared to your example – Alex Oct 31 '22 at 12:38
  • The ".htaccess" file is located at the wrong position, _inside_ the "batulabe" folder. I pointed out that detail above. If you use the rule with the "batulabe" folder named inside the capturing pattern, then you need to place that file outside that folder, one level further up, in the `DOCUMENT_ROOT` of the http host. – arkascha Oct 31 '22 at 12:56
  • my bad I got confused with what apache actually considers my root, following my different results. I just tried to change your 1st ex. a bit to ```RewriteCond %{REQUEST_URI} !^/public/pages/ ; RewriteRule ^(.*)$ /public/pages/$1.php [L]``` (without the semicolon of course) which gave a 404 instead of 500. Your second example, of course, still gave err 500. I've updated my link with the new logs. Tested ```http://my_pv4/batulabe/account```, first 10 lines are from 404 err that I've mentioned and the rest are 500 of your 2nd ex. – Alex Oct 31 '22 at 13:16
  • The issue is here: "rewrite 'account' -> '/public/pages/account.php'" ... I am confused. Sure you do not have a `RewriteBase /` somewhere in your configuration? I suggest you add a `RewriteBase /batulabe/` inside the ".htaccess" file inside the folder `batulabe`, right below the `RewriteEngine on`. – arkascha Oct 31 '22 at 18:35
  • Ah, sorry, no, the issue is that you did not copy the rule exactly, but modified it. In your last comment you said you now implemented the rule `RewriteRule ^(.*)$ /public/pages/$1.php [L]`. But that is _not_ what I posted in the answer. What I posted is: `RewriteRule ^(.*)$ public/pages/$1.php [L]`. Note the missing leading slash from the target. That is the difference between a relative and an absolute path. That is important! And it explains why the rewriting currently wrongly points to `/public/pages/account.php`. So no `RewriteBase` required, my confusion was justified ;-) – arkascha Oct 31 '22 at 18:50
  • okay, but the reason I tried modifying it was because your example leads to the loop error 500, like I've mentioned in the begging of the comments. Just tried to remove the slash again and the 500 happens again for both "new" and "old / full" URL's. One example that I've found on google that works is ```RewriteRule ^account?$ ./public/pages/account.php [L]``` but it's straight forward for just the account page and the full URL also works. Is there a way I can go about changing this rule to apply for all PHP files and making full URL not work? P.S. real big thanks for sticking so far! – Alex Nov 01 '22 at 12:56
  • To break the endless loop just replace the `L` flag with the `END` flag. I adjusted the rule in the answer above accordingly. – arkascha Nov 01 '22 at 15:15
  • finally! It worked! However, additional ```RewriteCond %{REQUEST_FILENAME}``` of "!-f" and "!-d" seemed to be needed as files like ```/batulabe/public/css/file.css``` and ```/batulabe/index.php``` lead to a 404 error otherwise. And yet with them around full URL also works. Is that unavoidable? I.e. make ```/batulabe/public/pages/...``` inaccessible at all unless it's the new rewrote URL? – Alex Nov 01 '22 at 23:12
  • That is an issue you never mentioned before. You now say that you need an exception to what you asked before. For that the condition you suggest might make sense, sure. An alternative might be to explicitly name specific paths as exceptions from the general rewriting rule. – arkascha Nov 02 '22 at 16:10
  • alright, gotcha, thanks for the help – Alex Nov 03 '22 at 10:01