Mobile app version of vmapp.org
Login or Join
Cugini213

: .htaccess wreaking havoc on site root! Help! I was taught that it is a good practice to separate publicly viewed webpages from included files and other, more sensitive information. That poses

@Cugini213

Posted in: #Directory #Htaccess #Subdirectory

I was taught that it is a good practice to separate publicly viewed webpages from included files and other, more sensitive information.

That poses a problem, however, when you wish to request index.php in the public folder.

Allow me to illustrate:

Site Root/
Includes/
-server_side_validation.php
Public/
-index.php
JS/
-js_form_validation.js
Sandbox/
Etc..


To get to index.php, I have to type in mywebsite.com/public/index.php, which is ugly.



So I learned a little about .htaccess and after a lot of trail and error I came to this code:

AddType application/x-httpd-php55 .php

# turn on rewrite engine
RewriteEngine on

## remove /public from host name
RewriteCond %{HTTP_HOST} ^www.mywebsite.ca$ [NC,OR]
RewriteCond %{HTTP_HOST} ^mywebsite.ca$
RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/ [L]


What this apparently does is turn mywebsite.com/public/index.php into mywebsite.com, essentially "hiding" the /public/index.php part but still requesting index.php.

That all works dandy until I try to execute a pretty routine user registration from my index.php page. It goes like this:

On index.php, I have a registration form and a JS script that validates the form then sends an AJAX request to ../includes/registration_val.php to validate again on the server side before database submission.

The JS validation file is inside the public folder, inside a JS folder. So one directory deep inside the public folder.

When I attempt to submit the form to the server_side_validation.php from js_form_validation.js, I get 404 Not Found. Upon inspection I see that the request goes to /public/includes/registration_val.php.

So it seems to imply that my code seems to mistake public/ as the site root instead of actual site root.

Now when I bypass the above .htaccess code, the problem goes away. So somewhere in my .htaccess I'm boning the whole thing up and I'm hoping one of you programmers much smarter than I can come to my rescue so I can get things back on track.

I want to keep that nice little benefit of clearing away the /public/index.php directory in favor of a nice clean mywebsite.com but without screwing up any internal directory traversing.

Muchas gracias!!

10.01% popularity Vote Up Vote Down


Login to follow query

More posts by @Cugini213

1 Comments

Sorted by latest first Latest Oldest Best

 

@Jamie184

As @Mike has already stated in comments, /public should be your DOCUMENT_ROOT and /includes should be entirely outside of your publicly viewable files, otherwise you are not really practising what you have been taught, to "separate publicly viewed webpages from included files and other, more sensitive information." Your files that you request via AJAX (publicly) should then go somewhere in the publicly accessible area.


That poses a problem, however, when you wish to request index.php in the public folder.


If /public is your document root, as it should be, then this is no longer a problem.


What this apparently does is turn mywebsite.com/public/index.php into mywebsite.com

The code shown above actually does the opposite. It quietly turns a request for mywebsite.com into mywebsite.com/public/. (mod_dir appends the index.php)


So it seems to imply that my code seems to mistake public/ as the site root instead of actual site root.


What your code does is prefix /public/ onto the URL if it doesn't already contain public/ - that is all. A request for /includes/registration_val.php doesn't contain public/, so the magic happens.

As mentioned above, /public should be your document root, however, as a quick fix, you can add a condition to exclude URLs that start /includes/ from being rewritten. Something like:

RewriteCond %{HTTP_HOST} ^(www.)?mywebsite.ca$ [NC]
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{REQUEST_URI} !^/includes/
RewriteRule (.*) /public/ [L]


I've changed the condition so that it matches /public/ at the start of the URL, rather than anywhere in the URL, as you had initially.

(www.)? - This combines your first two conditions by making the www subdomain optional. However, you should already have a canonical www/non-www redirect to resolve this anyway, so really you should only need to check for one or the other. And unless you have multiple hosts pointing to your webspace, you can remove this condition entirely.

(I assume your folders are really lowercase, as shown in your URLs. However, your directory structure shows capitalised first letters?)



Aside: It is always more efficient to do what you can in the RewriteRule pattern, rather than rely entirely on the RewriteCond directives above it. (.*) is going to match every request, so every request is going to be processed by this ruleset. This could be rewritten:

RewriteCond %{REQUEST_URI} !^/includes/
RewriteRule !^public/ /public%{REQUEST_URI} [L]


This first checks that the URL-path does not start public/ (directory prefix removed), and only then are the conditions processed.

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme