I have a static website with html files and I want to call them without the .html ending and a trailing slash.
For example:
www.test.com/test.html
Should be available under
www.test.com/test/
I managed this with the following .htaccess
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^\.]+)/$ $1.html
But both versions of the url lead to the same page. How can I redirect (without .html) or throw a 404 for the .html version?
www.test.com/test.html
This is the working solution with a trailing slash. Thank you #arkascha!
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^\.]+)/$ $1.html [END]
Well, add another rule that explicitly redirects requests to URLs with "file name extensions"...
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^/?([^\.]+)/?$ /$1.html [END]
If the above rule set results in a http status 500 ("server internal error"), then chances are that you operate a very old version of the apache http server. In that case you have to use the L flag instead of the END flag and add an additional condition to the first block:
RewriteEngine On
RewriteCond %{REQUEST_URI} .html$
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^/?([^\.]+)/?$ /$1.html [L]
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).
Related
.htaccess
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule foo foo\.php [NC,L]
With this setup the page /foo.php is accessible under example.com/foo while example.com/foo.php is still valid. How to permanently redirect from example.com/foo.php to example.com/foo?
Alternatively, how to permanently redirect from example.com/foo.php to example.com/bar?
This would be a combination of an external redirection to enforce the clean URL and an internal rewrite to make the actual script available:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.php$ /$1 [QSA,R=301,END]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^ %{REQUEST_FILENAME}.php [QSA,NC,END]
This code generally handles such tasks without being limited to a specific file name like "foo.php".
What you ask in your last sentence of the question is not possible right away. You cannot somehow rewrite a requested URL to two separate resources. How should the rewrite engine know which resource it should chose? So the question with that details is: what is it you really want to know with that question?
Taking from your comments that with the last sentence in your question you actually want to ask how to alternatively rewrite to a specific target I would like to add this example demonstrating how to add an explicit exception performing such redirection:
RewriteEngine on
# explicit internal rewriting to a fixed target
RewriteRule ^/?foo$ /bar.php [QSA,END]
# external redirection to enforce "clean URLs"
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.php$ /$1 [QSA,R=301,END]
# internal rewriting of "clean URLs"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^ %{REQUEST_FILENAME}.php [QSA,NC,END]
Need some help with htaccess rewrite rule I'm stuck with.
I have a handler index.html which is used to handle all requests except existing files.
I'm using this rule:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [L]
But I have some filenames similar to the requests to be handled. If there comes a request to /main it has to be handled by index.html but because of existing file with extension - main.asdfjaskldfjaskdfjasfd.js - I'm getting 404 error insted of handling.
This problem is super easily solved in nginx with one liner: "try_files $uri $uri/ /index.html;" but I don't have an opportunity to use nginx on production - only Apache.
So I need some help with those rules.
Tried (besides tens of other) this:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html
Full htaccess:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_URI} ^/(demo-auth|api|oauth|password|login|logout|register|images)
RewriteRule ^ laravel.php [L]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^ /index.html
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Thanks in advance.
Add that, at the top of your htaccess, to disable MultiViews:
Options -MultiViews
The Apache docs on mod_negotiation, describes what the Multiviews Option does, when enabled:
If the
server receives a request for /some/dir/foo and /some/dir/foo does not
exist, then the server reads the directory looking for all files named
foo.*, and effectively fakes up a type map which names all those
files, assigning them the same media types and content-encodings it
would have if the client had asked for one of them by name. It then
chooses the best match to the client's requirements, and returns that
document.
First off, I know there are many questions similar to this one. I've read everything I can find, but the solutions I see elsewhere don't seem to work for me. I'm really hoping someone can give me some insight here.
I am trying to use Apache's .htaccess directives to force specific pages on my server to use ssl. In addition to those directives, I'm also using some rewrites to mask .php and .html extensions.
I created a page, https-test.html. I want that page specifically to always get redirected so it uses https and so that .html gets stripped off, like https://www.example.com/https-test
However, I seem to always end up with a loop. Reading the Apache docs for 6 hours got me closer, but I'm still missing something.
Below is my annotated htaccess file.
RewriteEngine on
# If port is insecure...
RewriteCond %{SERVER_PORT} ^80$
# And requested URI is /https-test...
RewriteCond %{REQUEST_URI} ^(.*/)https-test$ [NC]
# Then point the server to the secure url:
RewriteRule . "https://www.example.com/https-test" [L,R]
# The next few lines try matching extensionless requests to .php files
# If the requested file is not a directory...
RewriteCond %{REQUEST_FILENAME} !-d
# And we CAN find a .php file matching that name...
RewriteCond %{REQUEST_FILENAME}\.php -f
# Then point us to that .php file and append the query string.
RewriteRule ^(.+)$ $1.php [L,QSA]
# These next few lines were added by the previous project owner
# They're supposed to redirect requests like /foo.html to /foo,
# But I suspect these might be the culprit
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)/$ /$1 [R=301,NE,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ /$1.html [NE,L]
# Next few lines are legacy SEO stuff, some pages were linked to as
# php but now are html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} .php$
RewriteRule ^(.*).php$ /$1.html [L,NE]
So that's the code I have in my htaccess. And if I go to http://www.example.com/https-test in Chrome, I get www.mysite.com redirected you too many times.
You should probably just rewrite the code a bit. You are trying to match both extensionless files to php and html and doesn't look like you're accounting for each of the conditions. You should add a condition to make sure they are not tryiing to do the same things.
Backup your code, replace your code with this and give it a try. Clear all your cache before trying.
RewriteEngine on
# If port is insecure... redirect for a specific page
RewriteCond %{HTTPS} !^on [OR]
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^http-test/?$ https://www.example.com%{REQUEST_URI} [R=301,L]
# Next few lines are legacy SEO stuff, some pages were linked to as
# php but now are html
RewriteCond %{THE_REQUEST} ^GET\ /(.+)\.php
RewriteRule ^ /%1? [R=301,L]
# The next few lines try matching extensionless requests to .php files
# If the requested file is not a directory and php file exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]
#remove trailing slash and is not a php file
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php !-f
RewriteRule ^([^\.]+)/$ /$1 [R=301,NE,L]
#finally redirect extensionless URI to html
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ /$1.html [NE,L]
Note I haven't tested this fully.
existingfolder is a folder containing an index.php file. I have some rewrite rules to make http://url.com/existingfolder/ redirect to that index.php. However, without the trailing slash, http://url.com/existingfolder, Chrome is stuck in loading and eventually leads to an error page.
I have tried numerous rules to get http://url.com/existingfolder (no trailing) work like the same as http://url.com/existingfolder/ (with trailing) with no success. My Apache version is 2.29 so I cannot use RewriteOptions AllowNoSlash. I don't use .htaccess instead I put all the rules in the config file.
RewriteEngine on
###I have tried:
DirectorySlash off
### I have also tried DirectorySlash on
RewriteEngine On
RewriteRule ^$ - [L,R=404]
###
#The rest of my rules
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteCond %{REQUEST_URI} !^.*\.(jpg|css|js|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule !.*\.php$ %{REQUEST_FILENAME}.php [QSA,L]
#redirect to index page inside the folder
RewriteCond %{THE_REQUEST} /index\.php [NC]
#remove php extension
RewriteRule ^([^\.]+)$ $1.php [NC,L]
This solution doesn't work at all. It makes things worse because http://url.com/existingfolder/ has become inaccessible. Can someone point me out what's wrong with the rules?
I have 7 URLs that are written:
http://www.example.com/TERMS/file
what I want is:
http://www.example.com/file
Problems are:
files aren't in my main directory so its a non-existing path, causing error:404 when I try rewriting it normally with mod_rewrite
I have file extensions turned off using the following:
> RewriteCond %{REQUEST_FILENAME} !-d RewriteCond
> %{REQUEST_FILENAME}\.php -f RewriteRule ^(.*)$ $1.php RewriteCond
> %{THE_REQUEST} ^[A-Z]+\ /([^/]+/)*[^.#?\ ]+\.php([#?][^\ ]*)?\ HTTP/
> RewriteRule ^(([^/]+/)*[^.]+)\.php /$1 [R=301,L]
which I believe is causing some conflict with the rewrites that I try doing.
If it helps, I also have mod_rewrite also forcing www on the address
I have tried looking for solutions on this site and have tried over 10 different methods, but none have worked for me.
and no, neither
> RewriteRule ^(.*)/TERMS/(.*) $1/$2
nor the
> (.+)
variation work for me.
You can use this rule after other rules in your DOCUMENT_ROOT/.htaccess file:
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^((?!TERMS/).+)$ /TERMS/$1 [L,NC]