I have managed to “rebase” the root from a directory in order to keep public files separated from configs, helpers, and controllers, thanks to this answer and this answer.
However I realized that if a user type http://domain.com/public
it will not redirect to http://domain.com
this is harmful for SEO because robots will treat them as two urls thus duplicate.
I need to 301 redirect /public
to root but as long as I am trying. It doesn’t work.
My htaccess looks like the following:
# Options
Options +FollowSymLinks +MultiViews -Indexes
DirectorySlash off
# Enable Rewrite Engine
RewriteEngine on
RewriteBase /
# Exceptions
RewriteCond %{REQUEST_URI} ^/(images|javascripts|stylesheets)/ [NC]
RewriteRule ^ - [L]
# www to non-www
RewriteCond %{HTTP_HOST} ^www.(.+)$ [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%2://%1%{REQUEST_URI} [L,R=301]
# Make /public like it was root
RewriteCond %{THE_REQUEST} /public/([^s]+) [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_URI} !^/public
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /public/$1 [NC,L,QSA]
# Error pages
ErrorDocument 403 /errors/403.php
ErrorDocument 404 /errors/404.php
ErrorDocument 500 /errors/500.php
<files .htaccess="">
order allow,deny
deny from all
</files>
In this way it will redirect to http://domain.com//
How can I fix this issue?
EDIT
My website directory structure is:
·
|__data
|__controllers
|__helpers
|__partials
|__layouts
|__images
|__javascripts
|__stylesheets
|__public
|__index.php
|__subfolder
|__index.php
In root there won’t be any index.php pages. So I need to make the /public
dir as it was my root, in order to keep configs and other directories that users don’t have to see separate.
3
Answers
There’s a number of things here that you need to address, but it appears that the core of it is here:
That block is going to generate a loop. It says “if the URL contains public, redirect it to root, but if it does NOT contain public, redirect it to public”.
I think what you’re trying to do is just:
It’s also worth pointing out that your block at the bottom isn’t going to do anything. I suspect that what you meant was:
However, for good measure, you might try
for all “dot-files”.
Replace your 2
public/
related rules to this:Without first trailing slash add rule if you use a URL for sub-directory e.g.
http://domain.com/subfolder
then after 3rd rule addingpublic/
in the URI it internally becomeshttp://domain.com/public/subfolder
which is a valid directory and Apache’smod_dir
module adds a trailing slash in the end doing a301
redirect tohttp://domain.com/public/subfolder/
and this will exposepublic/
part to your clients.When first trailing slash is there we check if destination is directory and add a trailing slash in original non-
/puclic/
URL itself.Ok, with your edit, it now appears that you’re asking the opposite of how I initially interpreted it. It kind of looks to me as though you’re introducing an additional layer of complexity in order to protect files that shouldn’t be inside the document directory to begin with.
What I would recommend is more from a security perspective than an httpd configuration perspective. If files aren’t meant to be public, move them out of the document directory. You’d end up with your regular content, plus images, js and css, in the document directory, and the rest of that stuff outside of it.
Failing that, if you insist on using mod_rewrite to accomplish this, I’d recommend something like the following:
However, note that this doesn’t actually solve the problem, since that “private” content is still there, inside the document directory, waiting for someone to figure out how to get at it.
What I’d recommend is that you take a step back and figure out what problem you’re actually trying to solve. If it’s the problem of private files being in the document root, the right solution is to move them out of that document root, not try to route around them being there.