Search code examples
apache.htaccessmod-rewriteurl-rewritingdocument-root

Redirect all existent and non-existent pages and folders within subfolder to one page when custom DocumentRoot set


I have the next file structure:

.htaccess
index.php
public/
├─ v1/
│  ├─ .htaccess
│  ├─ index.php
├─ index.php

I've set document root on server level to public subfolder in order to remove it from url.

I need all the requests containing v1 in url to be redirected to v1/index.php.

My root .htaccess:

RewriteEngine On
RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.php [NC,L]

and v1/.htaccess:

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} !-d  [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ index.php [QSA,L]

Expected behavior:

Non-existing https://example.com/v1/test page should redirect to https://example.com/v1/.

What I get instead:

Not Found
The requested URL was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

I am pretty sure the problem is in second .htaccess. I also suspect that custom Document Root can be a problem too here.


Solution

  • Try having your root .htaccess in following manner once and give it a shot and remove your inner .htaccess(keep backup of it in your local system though but don't have it on system). Clear your brorwser cache before testing your URLs.

    RewriteEngine ON
    
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond %{THE_REQUEST} !\s/public(?:/\S*)*\s [NC]
    RewriteCond %{THE_REQUEST} !\s/v1(?:/\S*)*\s [NC]
    RewriteRule ^(.*)/?$ /public/$1 [L]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{THE_REQUEST} !\s/v1(?:/\S*)*\s [NC]
    RewriteRule ^([^\.]+)$ $1.php [NC,L]
    
    RewriteCond %{THE_REQUEST} !\s/v1/?\s [NC]
    RewriteRule ^(v1)/.+/?$ /$1/? [R=301,L]
    
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^v1/?$  public/v1/index.php [QSA,L]
    

    NOTE: Will add detailed explanation in morning time as its too late night for me.