Rewrite condition to match ANY file extension - apache

I have the following htaccess rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L,R=301]
What this does is insert a trailing slash character to all my URLs, i.e:
http://localhost/advertising becomes http://localhost/advertising/
Now I have some URLs such as: http://localhost/contact.html
But my htaccess rule is applying the slash to these URLs too - so the above URL becomes http://localhost/contact.html/
Now I added the following condition to prevent this happening:
RewriteCond %{REQUEST_URI} !\.(html|php)$
But I want to be a bit more clever than this - I want a single expression that will match ANY extension the user types in. How can I achieve this?

This will rewrite all directories without trailing slash!
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)(\..{3,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]

Related

.htaccess - remove everything after third slash in path

On my website, I only use 3 slashes in my URL path:
https://example.com/this/isatest/
Right now I use .htaccess which makes it possible (as a side effect) to add as many stuff on the URL as you like:
https://example.com/this/isatest/hipperdihopperdus/pizza/bacon/with/cheese
I'd like to automatically remove everything after "isatest" while keeping the trailing slash using .htaccess.
This is what my .htaccess currently looks like:
Options -Indexes
Options +FollowSymLinks
RewriteEngine on
# 301 Redirect all requests that don't contain a dot or trailing slash to
# include a trailing slash
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*) %{REQUEST_URI}/ [R=301,L]
RewriteCond %{THE_REQUEST} /index\.html [NC]
RewriteRule ^index\.html$ /? [R=301,L,NC]
RewriteRule ^listen/$ /console/ [NC,L]
# Rewrites urls in the form of /parent/child/
# but only rewrites if the requested URL is not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?page=$1 [L,QSA]
How can I achieve this?
As your first rule, after the RewriteEngine directive, you can do something like the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
This checks if there is anything else (the dot) after two path segments and a slash, and redirects to removed "anything else".
Note that this is a 302 (temporary) redirect. Only change this to a 301 (permanent) redirect - if that is the intention - once you have confirmed that it works OK. This is to avoid the browser caching erroneous redirects whilst testing.
UPDATE: It may be more efficient to simply avoid redirecting files that end in a recognised file extension. Or perhaps exclude known directory location(s) of your static resources. For example:
RewriteCond %{REQUEST_URI} !\.(css|js|jpg|png|gif)$ [NC]
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
OR,
RewriteCond %{REQUEST_URI} !^/static-resources/
RewriteRule ^([^/]+/[^/]+/). /$1 [R=302,L]
You can add this rule just below RewriteEngine On line:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+/[^/]+/).+$ /$1 [R=301,L,NE]

.htaccess rewrite subfolders to remove /index

I have some htaccess rules which rewrite friendly URLs. Everything is working apart from one thing.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.*?)/?$ $1.html [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . / [L,R=301]
This is a site with language subfolders, e.g.:
/fr/about.html
/en/about.html
With the above htaccess rules these urls come out like:
/fr/about
/en/about
However this also means my index pages URLs look like:
/fr/index
/en/index
What I would like, is for /index the URL looks like
/fr
/en
Which would mean they respect the trailing slash part of my above htaccess but remove index from the URL.
Any help much appreciated!
Try to add (before RewriteCond %{THE_REQUEST} ^...):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s(.*?)/index(\.html)?[\s?] [NC]
RewriteRule ^ %1 [R=301,L]

URL rewriting reserved names

In my .htaccess file I have the following rewrite rule:
RewriteRule ^user/(.*) user.php?username=$1 [NC,L]
to take domain.com/user/anything and rewrite it to be used in my application.
However, I want to rewrite it to
domain.com/anything.
The only issue is, there are reserved file names that shouldn't be usernames when accessed, such as index (domain.com/index). What if the user has the name index?
You can use the following rule to exclude existent dirs and files from the rule :
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) user.php?username=$1 [NC,L]
If you want to exclude specific uris from the rule, you could use the following instead :
RewriteCond %{REQUEST_URI} !^/user.php [NC]
RewriteRule ^((?!index|upload|foo|bar).+) user.php?username=$1 [NC,L]

Rewrite URL with ?-sign

In .htaccess i want to rewrite the URL so...
http://example.com/folder/file.php?folder/images/image0001.jpg
Becomes...
http://example.com/folder/images/image0001.jpg
I have been trying...
RewriteRule ^folder/file.php?(.*)$ http://example.com/$1 [R=301,L]
But ends up with a unwanted ?-sign...
http://example.com/?folder/images/image0001.jpg
How do i get rid og the ?-sign ?
You can't match against the ? in a rewrite rule, you need to match against either in a %{QUERY_STRING} or in %{THE_REQUEST}. If you want to rewrite it to http://example.com/folder/images/image0001.jpg, meaning that the file **is actually at /folder/images/image0001.jpg, then you want this:
RewriteCond %{QUERY_STRING} ^(.+)$
RewriteRule ^folder/file\.php$ http://example.com/%1? [R=301,L]
If there isn't anything there, obviously that redirect will just result in a 404 Not Found. If this is supposed to be a way to make the URL look "pretty", then you need to rewrite the URL back to the query string:
RewriteCond %{THE_REQUEST} \ /+folder/file\.php\?([^&\ ]+)
RewriteRule ^folder/file\.php$ http://example.com/%1? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^folder/(.*)$ /folder/file.php?folder/$1 [L]

Non www to www redirect doesn't removes trailing backslash

I'm having a bit of problem with Apache redirect.
While bellow rules work for any page on site, mydomain.com will get redirected to mydomain.com//, which ignores trailing slash removal rule.
Also is it efficient to use multiple rules such as this or should I try to combine them or chain them somehow together in order to avoid multiple redirects for single url?
Thanks
#Turn on options for url rewriting
Options +FollowSymlinks
RewriteEngine on
#lovercase all urls
RewriteMap lc int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteCond %{REQUEST_URI} ^/fonts/.*
RewriteCond %{REQUEST_URI} ^/css/.*
RewriteCond %{REQUEST_URI} ^/js/.*
RewriteRule (.*) ${lc:$1} [R=301,L]
#redirect all requests made to http:// to http://www.
RewriteCond %{HTTP_HOST} ^mydomain\.com$ [NC]
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]
#removes trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]
The reason the mydomain.com gets redirected to www.mydomain.com// is because you have an extra "/" in your rewrite rule target:
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R=301,L]
^----here
When you have rules in your server/vhost config, the leading slash isn't removed so that gets match and used as a backreference, so mydomain.com is / which matches ^(.*)$ and the target becomes http://www.mydomain.com//. So you can either remove the slash in the target or add one to the regex:
RewriteRule ^(.*)$ http://www.mydomain.com$1 [R=301,L]
or
RewriteRule ^/(.*)$ http://www.mydomain.com/$1 [R=301,L]
Your other rule you have:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP_HOST} !^\.localhost$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}$1 [R=301,L]
are fine. They are for removing trailing slashes when there is something between them, e.g. /something/, because of the (.+). It wouldn't match // anyways because that inherently gets turned into just /. You just need to prevent redirecting to http://www.mydomain.com//