.htaccess Always hide a certain subdirectory from URL - regex

I'm trying to hide a subdirectory from the URL with .htaccess. I've got a PHP script which is executed everytime a client enters the website. It's index.php in root Apache directory. This script determines the language to use in the website and redirects to the target directory. English is my default language so what I need "en" directory to be hidden in the URL and at the same time redirect all the URL requests from root directory to "en" folder so they don't produce a 404 HTTP error. I partially achieved this with the following lines:
#Remove en/ directory from URL
RewriteRule ^$ en/
#Forward all the requests to en/ directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ en/$1
When requests are forwarded to "en" directory this is displayed again in the URL. This would be the flow:
User types: http://domain.com
index.php Redirects to http://domain.com/en because that's the detected language
.htaccess Rule hides /en directory, leaving the URL http://domain.com
Client types http://domain.com/panel to access their user panel
.htaccess Redirects to http://domain.com/en/panel
How can I remove "en" directory leaving the URL http://domain.com/panel after the last action in the list? Is there a better way to manage this behavior?
Current rules:
Options -Indexes +FollowSymlinks -MultiViews
ErrorDocument 404 /404.php
RewriteEngine On
RewriteRule ^/?$ en/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((?!en/).*)$ en/$1 [L,NC]
#Prevent direct access to PHP Scripts
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule \.php$ - [R=404,L]
#Remove WWW
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Have it this way:
Options -Indexes +FollowSymlinks -MultiViews
ErrorDocument 404 /404.php
RewriteEngine On
#Remove WWW
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L,NE]
# add a trailing slash if public/$1 is a directory
RewriteCond %{DOCUMENT_ROOT}/en/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L]
#Prevent direct access to PHP Scripts
RewriteCond %{THE_REQUEST} \.php[?/\s] [NC]
RewriteRule ^ - [R=404,L]
RewriteRule ^/?$ en/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^((?!en/).*)$ en/$1 [L,NC]
Clear your browser cache and test your flows.

Related

Redirect to public folder, with support for a trailing slash

This is my .htaccess file:
RewriteEngine On
DirectoryIndex index.php
#Set 404 and 505 pages
ErrorDocument 404 https://example.com/404/
ErrorDocument 500 https://example.com/500/
#Ignore AJAX requests
RewriteCond %{REQUEST_METHOD} ^(POST)$
RewriteCond %{HTTP:X-Requested-With} XMLHttpRequest [NC]
RewriteRule ^ - [L]
#Redirect 404 to correct page
RewriteCond %{REQUEST_URI} ^/404/$
RewriteRule ^(.*)$ /public/404.php [L]
#Redirect 500 to correct page
RewriteCond %{REQUEST_URI} ^/500/$
RewriteRule ^(.*)$ /public/500.php [L]
#Rewrite to /public folder
RewriteRule ^$ public/index.php [L]
RewriteRule ^((?!public/).*)$ public/$1 [L,NC]
#Hide .php extension
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]+)$ $1.php [NC,L]
/admin/ also has a .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]+)$ $1.php [NC,L]
It works fine, except in one situation.
The correct situations:
example.com/page -> Just shows the page
example.com/admin/ -> Works fine.
But if you enter example.com/admin (without the trailing slash), it redirects to /public/admin/.
I want to hide that public from my URL.
How to always get a clean URL, that always hides the /public from the URL.
Insert this redirect rule just before #Rewrite to /public folder line to add a trailing slash in the event if /public/admin/ is also a directory:
# add a trailing slash if public/$1 is a directory
RewriteCond %{DOCUMENT_ROOT}/public/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=301,NE]

removing php extension in htaccess returns an internal server error (500)

I'm trying to create a simple htaccess script which redirects users to the appropriate page. So, as an example, if the file/folder doesn't exist, a user navigating to /listing/id will be shown listing.php?id=id instead, or if they navigate to /username they will be shown profile.php?id=username.
The problem is, when accessing /listing/id, I retrieve an internal server error. But not because of the RewriteRule that handles this part - but because of the .php extension removal part of my htaccess script (I figured this out when I commented it out). I have no idea why this isn't working, as I believe I have the correct flags set, and am using the right block of code.
My Code
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# no php extension
# (/listing/id will work if this is commented out, but the other pages won't without the .php extension)
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# redirect to www.*
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com [R=301,L]
# only allow rewriting to paths that don't exist
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.+) - [PT,L]
# external profile.php?id=$id to /$id
RewriteCond %{THE_REQUEST} /profile\.php\?id=([\w-]+) [NC]
RewriteRule ^ /%1? [R=301,L]
# /listing/$id
RewriteRule ^listing/([\w-]+)/?$ listing.php?id=$1 [L,QSA,NC]
# /$username
RewriteRule ^([\w-]+)/?$ profile.php?id=$1 [L,QSA]
Example cases
/ (index) works
/search works (the file exists so it redirects to search page not a user named search)
/username works (username.php doesn't exist so it redirects to the profile page)
/listing/test returns Internal Server Error 500 (removing the no PHP extension part of my htacess causes this page to work normally, but now all the others will require .php to be appended)
All help is appreciated, Cheers.
Try your rules in this order:
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# redirect to www.*
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# external profile.php?id=$id to /$id
RewriteCond %{THE_REQUEST} /profile\.php\?id=([\w-]+)\s [NC]
RewriteRule ^ /%1? [R=301,L]
# only allow rewriting to paths that don't exist
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# /listing/$id
RewriteRule ^listing/([\w-]+)/?$ listing.php?id=$1 [L,QSA,NC]
# no php extension
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# /$username
RewriteRule ^([\w-]+)/?$ profile.php?id=$1 [L,QSA]

Getting .htaccess file to work in subfolders

I finally figured out how to get certain things to work on my website using the .htaccess file.
Redirect all non-www requests to www version. DONE.
Remove all php file extensions and add a trailing slash. DONE.
Prohibit directory views. DONE.
Limit caching. DONE.
Redirect 404 requests to home page. DONE.
This all seems to work well, but only in the ROOT directory.
It doesn't work well in subfolders. PHP extensions aren't removed. Folder paths in URLs disappear.
As I'm new to .htaccess files and regular expressions, and getting to this point took some time and lots of trial and error, I'm hesitant to tamper with the code any further.
I would appreciate any guidance on:
How to optimize this file for subfolders.
How to optimize this file in general.
Thank you.
RewriteEngine On
# redirect non-www requests to www version
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^example\.net [NC]
RewriteRule ^(.*)$ http://www.example.net/$1 [R=301,L]
RewriteCond %{HTTPS} on
RewriteCond %{HTTP_HOST} ^example\.net [NC]
RewriteRule ^(.*)$ https://www.example.net/$1 [R=301,L]
# remove .php file extensions
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
# disable directory view on web pages
Options -Indexes
# cached pages will expire in 5 days
ExpiresActive On
ExpiresDefault "access plus 5 days"
# re-direct 404 pages to home page
ErrorDocument 404 /
Keep your DocumentRoot/.htaccess like this:
# disable directory view on web pages
Options -Indexes
# cached pages will expire in 5 days
ExpiresActive On
ExpiresDefault "access plus 5 days"
# re-direct 404 pages to home page
ErrorDocument 404 /
RewriteEngine On
RewriteBase /
# redirect non-www requests to www (both http and https)
RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{HTTPS}s on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=302,L,NE]
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
## hide .php extension
# To externally redirect /dir/file.php to /dir/file
RewriteCond %{THE_REQUEST} \s/+(.*?/)?(?:index)?(.*?)\.php[\s?] [NC]
RewriteRule ^ /%1%2/ [R=302,L,NE]
# To internally forward /dir/file to /dir/file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^(.+?)/?$ $1.php [L]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.

Don't rewrite particular subfolder

I'm using the following .htaccess to rewrite all URLs to my index.php file if they're not actual files or folders:
Options +FollowSymLinks
RewriteEngine On
// This bit redirect www.mydomain.com to mydomain.com
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
// This bit redirects all requests to index.php if a file or directory
// bearing that name doesn't exist
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^.*$ ./index.php
I'm now adding an admin section to my website and I would like to not rewrite this particular URL:
mydomain.com/admin
I would like that case to be treated as it would be by default (in this case defaulting to mydomain.com/admin/index.php )
I've attempted to figure this out by myself but regex is still alien to me...
You can use:
Options +FollowSymLinks
RewriteEngine On
// This bit redirect www.mydomain.com to mydomain.com
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L,NE]
// This bit redirects all requests to index.php if a file or directory
// bearing that name doesn't exist OR it doesn't start with /admin/
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule !^admin/ ./index.php [L,NC]

URLs without www all redirect to home page

What do I need to do to redirect non-www URLs to their corresponding pages with www in the URL?
For example, there's a page called www.mysite.com/contactus. If try to access this site via mysite.com/contactus, it simply redirects to www.mysite.com.
Basically, I'd like all mysite.com/* to go to www.mysite.com/* instead of just going to the home page. Is this an htaccess configuration? Below is what I have for the mod_rewrite. Let me know if more information is required.
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_URI} !^/(media|skin|js)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule .* index.php [L]
</IfModule>
Insert this rule just below RewriteBase:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [NE,R=301,L]