Redirect request for directory-name to directory-name.html with htaccess - html

On my website, when somebody requests a directory, I want it to remove the '/' and add '.html' (minus the quotes, of course).
Example:
If someone goes to domain.com/directory/ it should redirect to domain.com/directory.html/ and the same should stand for: domain.com/another-directory/ should redirect to domain.com/another-directory.html.
I would like to place a line (or two) of code to my htaccess file that will make any directory (URL ending with /) redirect to URL.html (removing the / of course).
I would also like it to visually redirect, so the user will actually see it change to .html.
I'm quite a novice web programmer, and any help is greatly appreciated.
Note: I did use Redirect /directory /directory.html and that worked, but that requires a lot of extra coding, and I would much prefer one simple statement to cover all directories.

This is going to be a bit difficult with htaccess, I assume you want to do the following:
If someone accesses a directory that isn't the root (simply http://domain.com/), redirect them to the directory name ending with .html
After the get redirected, internally rewrite the .html back to the directory so apache can serve the directory.
First one is straightforward:
# check to make sure the request isn't actually for an html file
RewriteCond %{THE_REQUEST} !^([A-Z]{3,9})\ /(.+)\.html\ HTTP
# check to make sure the request is for a directory that exists
RewriteCond %{REQUEST_FILENAME} -d
# rewrite the directory to
RewriteRule ^(.+)/$ /$1.html [R]
Second part is tricky
# check to make sure the request IS for an html file
RewriteCond %{THE_REQUEST} ^([A-Z]{3,9})\ /(.+)\.html\ HTTP
# See if the directory exists if you strip off the .html
RewriteCond %{DOCUMENT_ROOT}/%2 -d
# Check for an internal rewrite token that we add
RewriteCond %{QUERY_STRING} !r=n
# if no token, rewrite and add token (so that directories with index.html won't get looped)
RewriteRule ^(.+)\.html /$1/?r=n [L,QSA]
However, if what you just have is a bunch of files called directory.html, directory2.html, directory3.html, etc. and you want to make it so when someone enters http://domain.com/directory2/ into their address bar they get served the contents of directory2.html, it will be much simpler:
# check to make sure the request isn't actually for an html file
RewriteCond %{THE_REQUEST} !^([A-Z]{3,9})\ /(.+)\.html\ HTTP
# check to see if the html file exists (need to do this to strip off the trailing /)
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.html -f
# rewrite
RewriteRule ^(.+)/$ /$1.html [L]

Related

how to remove the url extension

I am developing a website for myself, pure and without server language.
The urls are as they are called in the a tag, for example: blog / index.html.
Is there anything I can use to change that? I don't want to have to use framework. I would like to know if there is any tool that does this.
What I want to change is the ending. I don't want the extension to appear, just the route
try create .htaccess file on your root folder then paste this
#remove html file extension-e.g. https://example.com/file.html will become https://example.com/file
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html [NC,L]
you can read more about this here https://www.plothost.com/kb/how-to-remove-php-html-extensions-with-htaccess/
EDIT
Since you are using Vercel.com, as per their documentation there's a file config named vercel.json you can add this
{
"cleanUrls": true
}
the docs said,
When set to true, all HTML files and Serverless Functions will have their extension removed. When visiting a path that ends with the extension, a 308 response will redirect the client to the extensionless path.
for more information pls read their docs here https://vercel.com/docs/configuration#project/clean-urls

Htaccess rewrite html,htm,php to each other to help transition pages to the same file extension

I've currently got the following htaccess items which swaps html and htm file extensions back and forth, so if you try to load index.html but the only file that exists is index.htm it will serve that instead. It works vice versa too.
Goal is to move everything to PHP but in the meantime is it possible to extend this to cover php as well. So if one of the older html pages calls index.htm or index.html, it would find they don't exist and serve index.php instead. Likewise if you type index.php and it doesn't exist it would serve either the htm or html file.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1\.html -f [NC]
RewriteRule ^(.+?)(?:\.(?:htm))?$ /$1.html [L,NC,R=302]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}/$1\.htm -f [NC]
RewriteRule ^(.+?)(?:\.(?:html))?$ /$1.htm [L,NC,R=302]
Similar to .htaccess: rewrite .htm urls internally to .php, but also redirect .php urls to .htm but a little more complicated.
RewriteCond %{DOCUMENT_ROOT}/$1\.html -f [NC]
The NC flag is not supported when using -f. Whilst this isn't an "error" (the flag is simply ignored), your error log is likely to be littered with warnings.
There is also no need to backslash-escape the literal dot in the TestString (1st argument to the RewriteCond directive). This is evaluated as an ordinary string, not a regex.
RewriteRule ^(.+?)(?:\.(?:htm))?$ /$1.html [L,NC,R=302]
Since you've made the file-extension optional in the RewriteRule pattern, the regex matches everything, so you will end up testing everything, not just URLs that end in .htm (in this example). eg. Request /foo.htm and the above tests whether /foo.html exists (good), but request /foo.php and it tests if /foo.php.html exists (unnecessary).
You should be checking for a specific extension in each rule.
You are wanting to check every file extension, without prioritising any. It would be preferable (simpler, more efficient and arguably better SEO) to not use any file extension on the request and to prioritise file extensions that you want to serve. eg. Request /foo and serve .php if it exists, otherwise .html, otherwise .htm. Anyway, that's not what you are asking here.
The solution is similar to what you have already done, you just need to be methodical and test each combination. You can also use an optimisation and skip all the checks if the request already maps to an existing file.
Try the following:
# If the request already maps to a file then skip the following "5" rules
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [S=5]
# ----------
# Request .php, test .html
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^(.+)\.php$ /$1.html [NC,R=302,L]
# Request .php, test .htm
RewriteCond %{DOCUMENT_ROOT}/$1.htm -f
RewriteRule ^(.+)\.php$ /$1.htm [NC,R=302,L]
# ----------
# Request .html (or .htm), test .php
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+)\.html?$ /$1.php [NC,R=302,L]
# Request .html, test .htm
RewriteCond %{DOCUMENT_ROOT}/$1\.htm -f
RewriteRule ^(.+)\.html$ /$1.htm [NC,R=302,L]
# ----------
# Request .htm, test .html
RewriteCond %{DOCUMENT_ROOT}/$1\.html -f
RewriteRule ^(.+)\.htm$ /$1.html [NC,R=302,L]

How to htaccess 301 redirect pages with a question mark in the url

I'm trying to redirect several pages that all have question marks in the URL.
I essentially want to redirect:
www.example.com/?attachment_id=456 to www.example.com
There's a ton of pages with differend id #s also.
I've tried a few things in htaccess with no luck..
Any ideas?
This is what I tried:
RewriteCond %{QUERY_STRING} ^attachment_id=[0-9]
RewriteRule ^/$ http://www.example.com/? [L,NC,R=301]
Why can't you do this? This code should redirect a URL like this www.example.com/?attachment_id=456
RewriteCond %{QUERY_STRING} ^attachment_id=[0-9]+
RewriteRule ^/?$ http://www.example.com/? [L,NC,R=301]
I made the / optional so that it can be used in Apache config or .htaccess. Also I kept the ? that you have in the redirect at the end of the RewriteRule to remove any query strings on redirect.
Your approach is next to perfect, just some minor corrections:
RewriteEngine on
RewriteCond %{QUERY_STRING} attachment_id=[0-9]+
RewriteRule ^/$ http://www.example.com/ [L,R=301]
The above is the version for the host configuration. note that you have to restart the http server after having made changes to the host configuration for them to get effective. To debug refer to the http servers error log file, especially at restart time.
If you have to rely on .htaccess style files, then the syntax for the rule itself must unfortunately be slightly different:
RewriteEngine on
RewriteCond %{QUERY_STRING} attachment_id=[0-9]+
RewriteRule ^$ http://www.example.com/ [L,R=301]
Such file has to be located in the main folder of the document root of the host. also the interpretation of such files must be enabled in the host configuration by means of the AllowOverride option.
In general you should always prefer the host configuration for such rules over .htaccess style files, but you need administrative access for that. .htaccess style files are notoriously error prone, hard to debug and really slow the server down.

Clean/Short URLs using .htaccess is not working as it should

I've been following some YouTube videos to try and get this working but it doesn't seem to want to. This is how my .htaccess file is looking:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule RewriteRule ^(.*)$ index.php/$l
I am completely new to .htaccess, I'm not completely sure how it works but my common sense tells me to just create a file, call it .htaccess and place it in the same folder as my index.php, right?
So when I go to, say index.php/foo/bar or even just /foo/bar/ I get a 404 error.
What are the possible problems? It's a Windows 2008 Server with PHP 5.3.10 installed.
As beginning your last line should be
RewriteRule ^(.*)$ index.php/$l
And it should work as you expect it... pass all requests but ones for existing files/folders into index.php
The .htaccess can be in any folder which is hit by the request URL... the only difference is the base of the URL which is relative to the folder where is the .htaccess located
Example:
/folder1
.htaccess
index.php
/folder2
.htaccess
index.php
If you access /test.php none if your .htaccess files will be processed (it's not related to the request URI.
If you access /folder1/test.php the corresponding .htaccess in folder1 will be used and the $1 in your RewriteRule will show test.php, the /folder1/ will be stripped from the URI.
If you access /folder1/folder2/test.php it's similar... apache will use .htaccess from folder2... the one from folder1 will be ignored (a bit counderintuitive)

Using NC in a .htaccess file not working

I am trying to create an .htaccess file that ignores the case sensitivity of my files. I have the following so far:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html
This works when I type the file name exactly. For example, one of my files is About.html. When I type in www.domain.com/About, it goes to the right place, but when I type in www.domain.com/about, it does not.
I have seen posts about people using [NC], but I cannot get that to work either. I have also tried putting
CaseInsensitive On
But that seems to break everything (couldn't even load the home page), so I took that bit out. Does anyone have any idea on how to accomplish this?
Case insensitivity does not work like that, it activates case insensitivity for the regular expression matching, not the files.
For example :
RewriteRule ^somefile.php$ /index.php
RewriteRule ^somefile.php$ /index2.php [NC]
if someone try to access http://domain.com/SomeFile.php, it will not match the first line but the second line will, this will redirect him to index2.php (and not index.php). But if you the index2.php file is named instead INDEX2.php, the redirection will throw a 404 not found error.
What you are looking for is using RewriteMap. you need to put this in you server configuration file :
RewriteMap lc int:tolower
Restart apache, and use a rule in your htacces like this :
RewriteRule ^(.*)$ /${lc:$1}
This will turn any request to lower case, your files then must be all lowercased.
More informations about RewriteMap => see documentation