Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.htaccess, proper rewriting of directory and file with same name

Tags:

.htaccess

As of now my website has a few static pages, one of which is /portfolio. Among other things, my htaccess hides the .html extension. I'd like to add a portfolio directory, but I do not want to move my existing portfolio page into the portfolio directory as the default index file. My /portfolio page is one of my Google sitelinks and I am afraid if it is moved or if the url changes in someway, Google will consider it to be a brand new page.

My problem is once I add the /portfolio/ directory, whenever I try to visit the original /portfolio page, a trailing slash is automatically added and it links to the directory itself.

I've tried countless options, one being a rewrite of /portfolio/ to /portfolio, however this creates an infinite loop. I also tried "DirectorySlash Off" but that only removed the trailing slash while being inside the directory, it didn't revert access to the original /portfolio page.

Ultimately, I would like to keep my /portfolio page as-is, linking to pages inside the directory like so /portfolio/example and if either /portfolio or /portfolio/ is accessed it will result in showing the same page which is outside of the directory without Google thinking it is duplicate content.

A similar question exists here: .htaccess rewriting url to page or directory though this still resulted in an infinite loop for me for some reason, I'm guess it has something to do with the hidden extensions.

Here's my htaccess-

RewriteEngine On

# HTML to PHP
RemoveHandler .html .htm
AddType application/x-httpd-php .htm .html

# Hide extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html

# Force WWW
RewriteCond %{HTTP_HOST} ^mydomain\.net
RewriteRule ^(.*)$ http://www.mydomain.net/$1 [R=301,L]

# Blog Subdomain
RewriteCond %{HTTP_HOST} ^blog.mydomain.net$
RewriteRule ^(.*)$ http://www.mydomain.net/blog/$1 [R=301,L]

I know it's not a great idea having a directory with the same name as a static page, but I really would rather not alter the existing page and lose the Google sitelink, so a clean and proper way to handle this would be a help.

like image 596
PaulC Avatar asked Jan 07 '10 02:01

PaulC


People also ask

Does htaccess work on subdirectories?

htaccess file are applied to the directory in which the . htaccess file is found, and to all subdirectories thereof. However, it is important to also remember that there may have been . htaccess files in directories higher up.

What should htaccess file permissions be?

What permissions should the file have? 644 permissions are usually fine for an . htaccess file. When you create the file on the server, it should already have these permissions set, so there is most likely nothing to change.

What is rewrite base in htaccess?

What is RewriteBase. RewriteBase directive allows you to easily set the beginning of all relative paths used in . htaccess file. Its value is used in the target/destination path mentioned in rewrite rules in . htaccess file.

How do I know if htaccess rewrite is working?

Save the file and type the URL yoursite.com/foobar/ . If the reditect works and the URL gets redireted to the homepage of example.com then it's clear that your htaccess is working and being read by your Apache server. If it still doesn't work then the problem might be that your hosting provider has not enabled it.


1 Answers

There are two things going "wrong" here, and two ways to fix it.

The first is that apache "figures out" that there is a directory by the name of "portfolio" before the rewrite conditions are applied. That means that the rewrite conditions are receiving "portfolio/" instead of "portfolio".

Second, the "!-d" rule is specifically avoiding the rewrite that you want to make if there is in fact a directory by that name

Solution 1: Manually re-route requests for the portfolio directory to remove the slash.

# Manually re-route portfolio/ requests to portfolio
RewriteCond %{REQUEST_FILENAME} portfolio/$
RewriteRule ^(.*)/$ $1 

# Hide extension
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html

Note the removal of the "!-d" condition.

The downside to this is that you are having to hard-code the "portfolio" edge case directly into the rewrite rules, and will still result in the browser being first redirected to portfolio/

Solution 2: Set DirectorySlash Off and remove directory exists test

# Disable Automatic Directory detection
DirectorySlash Off

# Hide extension
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html

Setting DirectorySlash Off would fix this issue the best, but may break other parts of your site where you actually want the auto DirectorySlash. Best of Luck, and I hope this helps.

Note when testing solution 2, your browser may remember the redirect of "portfolio" to "portfolio/" and perform the redirect before it even sends the request to the server. Be sure to test in a cache-clear, clean environment for best results.

like image 175
James Maroney Avatar answered Sep 28 '22 06:09

James Maroney