.htaccess redirect from site root to public folder, hiding "public" in URL?
Asked Answered
G

7

31

Bellow is my site directory structure:

htdocs/
    My-Project/
        public/
            index.php
            css/
            img/
            js/
        src/
            config.php
            templates/
            library/

I do not want any direct user access to any files inside the src directory. src contains my templating and backend logic scripts.

I want to set up my .htaccess so that when the user goes to my website (root folder My-Project), they are redirected to My-Project/public/index.php. I would like the URL to simply look like My-Project.com while on the index page.

Any help? I am hesitant to modify my .htaccess file as I see a lot of conflicting advice around here and on the net as to the best way to do this.

Graehme answered 13/5, 2014 at 15:40 Comment(7)
Why the need for a public directory in the first place, incidentally?Blakeslee
If you're on shared hosting then the only way to do what you want would be through the .htaccess. If you have a VPS then you can point the server to that public folder using the hosting settings.Unicameral
@AndrewBarber: I suppose there isn't a requirement for it, I'm just trying to keep my front-end and logic code as separate as possible and this structure helps me stay organized. I'm open to recommendations though, I'm new to larger PHP projects :)Graehme
Well, it's usually expected that a site's root directory would be the 'public' part. But if you have code that you don't want accessed at all via requests, it should be out of the web directory entirely, as @Unicameral notes.Blakeslee
@CheckeredMichael: yes shared hosting. I know I need to do it via .htaccess I'm just not sure which commands would accomplish both of the things I need. Would I need a .htaccess in the root to redirect to the /public/ folder, and then another inside /public/ to format the URL?Graehme
@AndrewBarber: I don't want users to be able to directly visit any of the src directories, but the scripts in public directory should be able to access them.Graehme
You could also do it via PHP, if you add a header to the index of My-Project.Matos
C
73

Place this code in /My-Project/.htaccess:

RewriteEngine On
RewriteBase /My-Project/

RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]

RewriteRule ^((?!public/).*)$ public/$1 [L,NC]
Corody answered 13/5, 2014 at 17:46 Comment(5)
This is partially working, everything loads except images which are returning 404's. this is because I'm using retina images for PHP, which has me create a .htaccess in the /public/ dir, it redirects image requests to retina-equivalents. Is there a way to make these two methods play nice together?Graehme
It can be done, can you post your .htaccess from /My-Project/public/.htaccess?Corody
@pathros: It is working and tested solution. You can post a new question with all the details to get your problem resolved.Corody
I get Request exceeded the limit of 10 internal redirects due to probable configuration error. This worked for me.Somnambulation
Note: If you're using XAMPP or similar, your /htdocs/my-project/.htaccess file should use RewriteBase /my-project/ too!Assuming
G
11

Add the following to the first line of your .htaccess

DirectoryIndex public/index.php public/index.html
Gumption answered 6/4, 2015 at 15:5 Comment(2)
@Pathros be sure to put it after the rewrite engine statementFoamy
@anubhava's answer is better because it will redirect all http requests, this answer won't redirect css and js resources queries for exampleMadelinemadella
M
11

this works for me all the time. Create a .htaccess in your root directory outside of the public folder then add these 3 lines and boom problem solve.

RewriteEngine On
RewriteCond %{REQUEST_URI} !^public
RewriteRule ^(.*)$ public/$1 [L]
Muddy answered 11/6, 2020 at 3:14 Comment(2)
It works, but if I put public in the URL it also works, and since Google has indexed the URL with public. Do you know any way to redirect URLs with public to without public? I have tried to put this: RewriteRule ^public/(.*)$ /$1 [R=301,L] but it doesn't work.Ecumenism
Because we route everything to the /public you must before that code above specify the URL so it can then properly find the route. In your public folder create a new htaccess and add this code RewriteEngine on RewriteRule ^public/(.+)$ example.com/$2 [R=301,L] replace the url with your own urlMuddy
S
10

I made some changes to @anubhava's response to working on localhost and with friendly URLs.

Directory structure:

  • / (localhost root folder)
    • myapp/
      • public/
      • index.php
    • core/
      • some core files ...

myapp/.htaccess (myapp root folder)

RewriteEngine On
RewriteBase /myapp

RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]
RewriteRule ^(.*)$ public/index.php?$1 [L,QSA]

myapp/public/.htaccess

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]

myapp/public/index.php

<?php
echo 'Hello<br>';
echo $_SERVER['QUERY_STRING'];

Some requests:

http://localhost/myapp/

Hello


http://localhost/myapp/post/new

Hello

post/new

Squint answered 7/2, 2018 at 21:37 Comment(1)
seems to only load pub/index.php - not load the relevant page?Sixpence
I
5

I was looking for a same solution for my "pet project" deployed on a free web hosting Infinityfree.

The directory structure (before):

htdocs/
   ├─ public/
   └─ src/

None of the answers above separately didn't help me and caused 404 or 503 http errors or just showed me folders of a project.

SandroMarques' answer encouraged me to try add two .htaccess files. After multiple attempts, I found a solution that worked for me. I used anubhava's and SandroMarques' answers.

The directory structure (after):

htdocs/
   ├─ public/
   │   └─.htaccess //second file
   │
   ├─ src/
   └─.htaccess //first file

First .htaccess file:

RewriteEngine On
RewriteBase /

RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]

RewriteRule ^((?!public/).*)$ public/$1 [L,NC]

Second .htaccess file:

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]

Maybe others will find this helpful.

Inhalation answered 28/3, 2023 at 9:9 Comment(0)
V
0

ok so you can do this , with symfony 5, if you want to put a .htaccess to redirect the access to public/index.php file you have this:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ public/index.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ public/index.php [QSA,L]
and you can add this to redirect to https if you have a certificate for let's encrypt for example :
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
Visa answered 9/5, 2023 at 20:43 Comment(0)
G
0

You need just to add .htaccess file into the public folder contain this code:

RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]

note:if you put this code on root folder it will doesn't works

Gus answered 5/7 at 7:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.