Mobile app version of vmapp.org
Login or Join
Margaret670

: .htaccess Direct all requests to Public dir when using framework etc I using this .htaccess code to direct all requests to Public directory: <IfModule mod_rewrite.c> RewriteEngine

@Margaret670

Posted in: #Apache #Htaccess #Laravel #ModRewrite

I using this .htaccess code to direct all requests to Public directory:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteRule ^(.*)$ public/ [L]
</IfModule>


Site structure:

Public_html/
app/
public/
app/
css/
index.php
index.php


This code works fine but fails when I hit on existing directories in root:

example.com/css -> public_html/public/css - works ok example.com/app -> public_html/app - not ok, must be public_html/public/app


How to ignore existing directories and rewrite everything to public dir

10.01% popularity Vote Up Vote Down


Login to follow query

More posts by @Margaret670

1 Comments

Sorted by latest first Latest Oldest Best

 

@Jamie184

This code works fine


You must have something else... the code you have posted would result in a rewrite loop (500 Internal Server Error) for all requests?

But neither do you have to do anything special to "ignore existing directories and rewrite everything to public dir". So again, there must be something else going on here?

However, what you do need to do in order to avoid a rewrite loop is to include a condition to avoid rewriting to the "public" subdirectory when you have already rewritten to the "public" subdirectory. For example:

RewriteCond %{REQUEST_URI} !^/public/
RewriteRule (.*) public/ [L]


Without the RewriteCond directive /something would get rewritten to /public/something to /public/public/something to /public/public/public/something, etc...

Incidentally, you don't need anchors (^ and $) if you are matching the entire string, so ^(.*)$ and (.*) are the same.


<IfModule mod_rewrite.c>


Aside: Unless your site is intended to "work" without mod_rewrite, you should remove the <IfModule...> wrapper.

UPDATE:


Comment: the existing .htaccess is from laravel developers:

<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>

RewriteEngine On

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ / [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>



Ok, this makes more sense, but it's also part of the "problem". You can't just add another directive and expect it to work. You need to work with the existing directives (if that is the intention). The order of the mod_rewrite directives is important.

This is made more complex because you wish to ignore existing files and directories in the document root (as per your question). Also, the /public subdirectory presumably needs to be kept private, otherwise we could simply redirect. The "Redirect Trailing Slashes" then becomes a bit tricky as we can't redirect to the /public directory (since that obviously exposes the hidden directory), but we need to check the existence of directories in that directory, not the document root (in which we are currently located). You also need to block direct access to the /public directory (or rather redirect back to the root).

Try the following (just the inner, mod_rewrite directives are included after RewriteEngine):

# Prevent direct access to the "public" folder - redirect to root
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9} /public/
RewriteRule ^public/(.*) / [R=302,L]

# Redirect Trailing Slashes If Not A Folder...
# - but look for the file in the "public" folder
# (ensure we are not already in the "public" folder)
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{DOCUMENT_ROOT}/public/ !-d
RewriteRule ^(.*)/$ / [R=302,L]

# Rewrite "everything" to the "public" subdirectory if not already
# This ignores existing files/dirs in the document root
RewriteCond %{REQUEST_URI} ^/(.*)
RewriteRule !^public/ public/%1

# Handle Front Controller... (as before)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]


Make sure you clear the browser cache before testing, since the previous (erroneous) 301 redirects will have been cached by the browser.

Change the 302 (temporary) redirects to 301 when you are sure it's working OK. (302s aren't cached by the browser, so makes testing easier.)

10% popularity Vote Up Vote Down


Back to top | Use Dark Theme