Remove .php from URL and force a trailing slash / - .htaccess

I want to use .htaccess mod_rewrite to remove .php from all my files and force a trailing slash /. However, it is only resulting in me getting server errors.

You want to map :
http://sampledomain.ext/index/ -> http://sampledomain.ext/index.html
Use the following .htaccess
RewriteEngine On
RewriteCond %{REQUEST_URI} ! \.php$ #Avoid real php page, do what you want with them
RewriteCond %{REQUEST_URI} /$ #Ensure a final slash
RewriteRule ^(.*)$ $1.php #Add your extension
Tx to David Wolever who write quitely the same stuff 1
If I can give my opinion, it's a little bit strange to force the / at the end for a file no?

Related

Url redirection - changing folder, replacing underscores with dashes and removing html extension

I have an old site where I have underscores and an html extension which I want to redirect in the following way
http://example.com/news/this_is_a_test.html -> http://example.com/post/this-is-a-test
http://example.com/portfolio/another_test.html -> http://example.com/project/another-test
There are other folders apart from news and portfolio and clearly the final segment of the url has an unknown number of underscores.
Here is the .htaccess I am using at the moment (based on my original question htaccess file to remove folder, and replace underscores with dashes). It works for the news example, but breaks if I try for portfolio.
Any idea where I'm going wrong?
RewriteEngine on
# redirect "/news_bar" to "/foo_bar"
RewriteRule ^news/(.+)$ /$1 [L,R]
#2 replace underscore with hypens
RewriteRule (.*)_(.*) $1-$2 [N,E=uscores:yes]
RewriteCond %{ENV:uscores} yes
RewriteRule ^(.+)$ /post/$1 [L,R]
RewriteRule ^portfolio/(.+)$ /$1 [L,R]
RewriteRule (.*)_(.*) $1-$2 [N,E=uscores:yes]
RewriteCond %{ENV:uscores} yes
RewriteRule ^(.+)$ /project/$1 [L,R]
# remove .html from end of url
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]
Many thanks!
I had a solution for this before, but it is breaking on my current setup (Apache crashes), and so it would be unwise of me to recommend it for your case. (It could be an issue with my setup, but I'd prefer to give you a more straight-forward route.)
This solution involves sending the relevant requests to a PHP file that will do the necessary replacements, and redirect once only. Note that your current implementation will send multiple redirect instructions to the browser. This is not only bad from a user experience point of view, but also from an SEO one.
To implement the solution, start by replacing your .htaccess directives with this:
RewriteEngine On
# Rewrite news and portfolio links to redirect.php
RewriteRule ^(news|portfolio)/(.+).html /redirect.php [L]
Then, create a redirect.php file in the same directory as your .htaccess file (in this case, your document root), and fill it with this simple replacement method and redirect instruction:
<?php
$path = $_SERVER['REQUEST_URI'];
# Perform the necessary replacements. The first array contains
# what we're searching for, bit by bit, and the second array
# contains the relevant replacements.
$path = str_replace(
['_', '/news/', '/portfolio/', '.html'],
['-', '/post/', '/project/', ''],
$path);
# Now, simply redirect to the new path.
# Change 302 to 301 use a "Moved Permanently" header,
# resulting in browsers and search engines caching
# the redirect.
header("Location: $path", true, 302);

How to remove subdirectories and replace file extensions with a trailing slash

The following is my directory structure
Root (example.com)/
index.htm
contact.htm
privacy.htm
disclaimer.htm
cat/
play/
fun.htm
rest/
sleep.htm
I managed to remove the file extension and add a trailing slash with:
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R,L]
But I also want to make it in such a way that when people go to www.example.com/fun/ they're able to access www.example.com/cat/play/fun.htm without redirecting, which means, in the address bar it still shows www.example.com/fun/.
I know I can use the direct approach like:
RewriteRule ^fun/$ /cat/play/fun.htm [L]
RewriteRule ^sleep/$ /cat/rest/sleep.htm [L]
But I'll be adding more files to these 2 subdirectories (/cat/play/ and /cat/rest/), so I was wondering if there's a single rewrite rule to perform the rewrites for these files instead of having to enter 100 rewrite rules for 100 files under those 2 subdirectories. Please enlighten.
Appreciate your help.
Put these lines in .htaccess
RewriteRule ^fun/?$ play/fun.htm [L]
RewriteRule ^sleep/?$ rest/sleep.htm [L]
They cannot be moved to one rule, so they should be used with separate rules for each URL.

hide html extension + redirect .html version + special case exception

I have a hard time understanding htaccess mod_rewrite and while I found several related questions + answers, I unfortunately can't get my very specific situation to work correctly (mod_rewrite is even after hours of searching a book of seven seals to me to be honest)
I have foo.html and bar.html within my root directory. Now, I'd like to have foo.html as the default directory index (solved, easy), but from there I do not get it.
What I want to achieve is:
hiding the .html extensions
user should be able to type /bar to get /bar.html without seeing the .html (for every .html)
301 redirecting .html version
user should be able to type /bar.html and see /bar in the url (avoid duplicate, for every .html)
The most tricky part:
As foo.html is default directory index, typing / already shows (transparently) /foo.html, but I need typing /foo.html to resolve to / as well as typing /foo to resolve to /
Try putting these rules in the htaccess file in your document root:
RewriteEngine
# 1. hiding the .html extensions
RewriteCond %{REQUEST_URI} ^/(.*?)/?$
RewriteCond %{DOCUMENT_ROOT}/%1.html -f
RewriteRule ^ /%1.html [L]
# 2. 301 redirecting .html version
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.html
RewriteCond %1 !foo$
RewriteRule ^ /%1 [L,R=301]
# 3. typing /foo.html to resolve to / as well as typing /foo to resolve to /
RewriteCond %{REQUEST_URI} ^/(.*?/?)foo(\.html)?$
RewriteRule ^ /%1 [L,R=301]
Also, make sure you have Multiviews turned off:
Options -Multiviews
The first rule has 2 conditions, the first groups the URI everything between the first / and a possible last /. The references it using %1 in the next condition which sees if the /path/to/www/document/root/%1.html is a file that exists. If both are true, it internally rewrites the URI to include a .html at the end.
The second rule has 2 conditions, the first matches against the actual request as opposed to the URI (which can change as the rules are being applied and rewrites happen). It sees if there's a request that ends with .html, and if so, the second condition makes sure that it isn't foo.html request (since the last rule handles that). If both are true, then it redirects the browser to the part of the URI without the html, again using %1 to reference the grouping in the match from the first condition ([^\ ]+).
The last rule checks if the request is for a foo or foo.html. If so, redirect removing that part of the URI.
I am using the one below and it works except that, in some strange case when working with a WARRANTY script for a client it just won't do the thing.
However; the other scripts that calls external scripts via iFrame in a sub-folder seems to work with the exception of the WARRANTY script. ...
Options +FollowSymLinks -MultiViews
RewriteEngine on
RewriteBase /
RewriteCond %{ENV:REDIRECT_END} =1
RewriteRule ^ - [L,NS]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*?)\.(php|html?)$ $1 [R=301,NC,NS]
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)$ $1.html [L,E=END:1,NS]
RewriteCond %{REQUEST_FILENAME}\.htm -f
RewriteRule (.*)$ $1.htm [L,E=END:1,NS]
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)$ $1.php [L,E=END:1,NS]
I hope this Helps.

How do I remove a trailing slash?

I just want to remove a trailing slash from a directory. For example I want /p/page/ to show up as /p/page. It just looks better, doesn't it?
However I've tried many different kinds of mod_rewrites but none have worked or something happened.
I just want this to apply to subfolders (even better, any slash in a folder in a folder in a folder like /a/b/c), not /p/ as this may affect other parts of my site in a negative way.
You can try adding the following line to your .htaccess file:
DirectorySlash Off
That solved the problem for me a while ago. Of course if the path is only / I don't think you can get rid of it.
Copy this code in your root .htaccess file (directly under DOCUMENT_ROOT):
Options +FollowSymLinks
RewriteEngine on
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^ %{REQUEST_URI}/ [L]
DirectorySlash Off
RewriteCond %{THE_REQUEST} ^GET\s(.*)/\s
RewriteRule ^ %1 [R=302,NE,L]
It will externally redirect http://localhost/blog/ to http://localhost/blog while still displaying default index.html or index.php or whatever under /blog directory.

.htaccess falling over on trailing slash

TL;DR
How can I get .htaccess to rewrite http://domain.com/images to http://domain.com/images/ (i.e. add a trailing slash to URLs without one)? The URLs can be deeper than one level, for example http://domain.com/images/page/1.
More info
Say I have a URL like this:
http://jamwaffles2/wallpapers
This will redirect to this in the URL bar, with the rewrite rule working fine:
http://jamwaffles2/wallpapers/?page=wallpapers
However
http://jamwaffles2/wallpapers/ (note trailing slash)
Rewrites fine to
http://jamwaffles2/index.php?page=wallpapers (not visible to user)
With a nice http://jamwaffles2/wallpapers/ in the address bar.
The issue here is that when a trailing slash isn't given to the URL, the URL in the address bar changes to a not-so-pretty one. Can someone offer a solution to this?
Here's my .htaccess:
# turn rewriting on
RewriteEngine on
RedirectMatch permanent ^/$ http://jamwaffles2/home
Options +FollowSymLinks
RewriteRule ^([^/\.]+)/?$ /index.php?page=$1 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2&var2=$3 [L,NC,QSA]
RewriteRule ^([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /index.php?page=$1&var1=$2&var2=$3&var3=$4 [L,NC,QSA]
As a side note, there are more levels to the URL; the .htaccess should make that apparent (e.g. http://jamwaffles2/home/page/2).
EDIT
Curiously, this only happens on /wallpapers. If I type in http://jamwaffles2/home it works as expected, but won't work with http://jamwaffles2/wallpapers.
1) Try this directive: Options +FollowSymLinks -MultiViews -- depending on Apache config it can be the deal breaker.
2) Use this code (one of possible variants) to add trailing slash for NON-EXISTING resources ONLY:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
It will redirect (301 Permanent Redirect) so URL will change in browser (e.g. example.com/hello => example.com/hello/).
If it still does not work (for whatever the reason may be) -- if you can edit Apache config files -- please enable rewrite debugging (RewriteLogLevel 9) and check the rewrite log to see why some URL failing correct rewrite. Every server can be configured differently, so the same rule may work a bit differently in your case.

Resources