mod_rewrite making a directory available from all directories/subdirectorries - apache

I want to link a directory like:
/resources/IMG/
to all other directories like
/IMG/ would resolve to /resources/IMG/
and also
/foo/IMG/bar/anything.img should resolve to /resources/IMG/bar/anything.img
with .htaccess. I have tested several methods of doing this, which one would be the best working one?
EDIT: SOLUTION
# Add trailing slash to any directory if not done so
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
# MAP /resources/IMG/ to be avaible as /IMG/ from everywhere
RewriteCond %{REQUEST_URI} !^/resources/IMG/
RewriteRule ^(?:.*/IMG/)(.*)$ /resources/IMG/$1 [L]
The best way of dealing with /IMG (without trailing slash) is to firs map it and then add the slash, but since it is a 301 redirect it will refresh the REQUESTED_URI and the url will be /resources/IMG/ but if you always add a trailing slash it should work fine.

You can use this rule as your very first rule:
DirectorySlash Off
# Add trailing slash to any directory if not done so
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
RewriteCond %{REQUEST_URI} !^/resources/IMG [NC]
RewriteRule ^(?:.*?/)?(IMG(?:/.*)?)$ /resources/$1 [L,NC]

Related

Remove the subfolder from the url path, given that there is no slash at the end

I have the htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /pages/$1 [L]
it removes /pages/ from the url to the pages
but when i open link without the slash at the end:
site.com/contacts
it is redirected to
site.com/pages/contacts/
Is there a way to fix this?
I've tried different results, most often other options cause a redirect to site.com/index.php ( site.com/pages/index.php)
It is happening because pages/contacts is a directory and Apache mod_dir module is adding a trailing slash after request to a directory.
You can check for directory presence and add a trailing / via a rule before rewrite to pages/:
RewriteEngine On
# add a trailing slash if pages/$1 is a directory
RewriteCond %{DOCUMENT_ROOT}/pages/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=301,NE]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /pages/$1 [L]
Make sure to use a different browser or remove cache data from your browser to test this rule to avoid old cache.

.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]

make .htaccess to prevent navigating to directories

I have this .htaccess
DirectorySlash On
RewriteEngine On
RewriteRule /?\.htaccess$ - [F,L]
# Remove trailing slash
RewriteRule ^(.*)/$ /project/$1 [R,L]
# Map every link to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/project/index.php.*$
RewriteRule ^(.*)$ /project/index.php?___MYROUTER=$1 [QSA,END]
but when I'm navigating to one of directories next to my .htaccess file like css folder in browser, with this address:
http://localhost/project/css
then my address will be changes to:
http://localhost/project/css?___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css&___MYROUTER=css
and in firefox this is the result:
The page isn’t redirecting properly
Firefox has detected that the server is redirecting the request for
this address in a way that will never complete.
This problem can sometimes be caused by disabling or refusing to accept cookies.
but other addresses those are not pointing to an existing directory, will be ok like:
http://localhost/project/mycontroller
this address is ok and will not be changed to anything else
What is the problem with my .htaccess?
this is my log file
That is because Apache is adding a trailing slash in front of directories after mod_dir module has completed execution.
You can add a trailing slash in front of directories yourself using a separate rule.
DirectorySlash On
RewriteEngine On
RewriteRule /?\.htaccess$ - [F,L]
# Remove trailing slash for non directories
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /project/$1 [R,L]
# add a trailing slash to directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=301,NE]
# Map every link to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/project/index\.php [NC]
RewriteRule ^(.*)$ project/index.php?___MYROUTER=$1 [QSA,END]

Redirect to index.php in root

I've written the following code in my htaccess file:
RewriteRule ^(.*)/$ $1
RewriteCond %{REQUEST_URI} !^index.php.*$
RewriteRule ^(.*)$ /index.php?route=$1 [END]
It works perfect for every path, except for directories that exist. For example, if I enter http://localhost/profilepic and such directory actually exists, it redirects to http://localhost/profilepic/?route=profilepic, but I want it to be implicitly converted to http://localhost/index.php?route=profilepic.
Thanks in advance.
The reason this is happening is because of mod_dir and the DirectorySlash directive. Essentially, if it sees a URI without a trailing slash, and it maps to an existing directory, then it'll redirect the request so that it has the trailing slash. Since mod_dir and mod_rewrite are both in different places in URL-file processing pipeline, both mod_dir and mod_rewrite get applied to the same URL. That's why you end up with a redirect and a weird URL with the query string.
If you absolutely must have directories without trailing slashes, then you need to turn of DirectorySlash. The problem with turning it off is that there is an information disclosure security concern that will make it so people can look at the contents of a directory even if you have an index file. That means you have to make up for mod_dir using mod_rewrite.
So get rid of the rule:
RewriteRule ^(.*)/$ $1
and replace it with these rules:
DirectorySlash Off
# redirect direct requests that end with a slash to remove the slash.
RewriteCond %{THE_REQUEST} \ /+[^\?\ ]+/($|\ |\?)
RewriteRule ^(.*)/$ /$1 [L,R]
# internally add the trailing slash for directories
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*[^/])$ /$1/ [L]
Here is another way you can have your rules without turning off DirectorySlash (considered a security hole):
RewriteEngine On
# remove trailing slash for non-directories
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
RewriteRule ^(.+?)/$ /$1 [R=301,L]
# routing for directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+?)/$ /index.php?route=$1 [L]
# routing for non directories
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+?)/?$ /index.php?route=$1 [L]

mod_rewrite: add trailing slash?

I am using a .htaccess file to direct requests for a directory to a custom php file that provides info about that directory (and i want the url displayed by the browser to not change).
Here is the relevant part of the .htaccess file.
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ /myphp.php?url=%{REQUEST_URI} [QSA,L]
This works well if you go to a directory and include a trailing slash:
http://domain.com/path/
But without the trailing slash, it doesn't
http://domain.com/path
The url (shown in the browser) turns into:
http://localhost:8888/path/?url=/path
I've tried fixing this by adding a rule above this rule:
RewriteCond %{REQUEST_FILENAME} -D
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L]
But that isn't working for me.
How can I get .htaccess to add the trailing slash if it is omitted and then act just as if it had been there?
Thank you
Update:
As requested, here is the whole thing.
<IfModule mod_rewrite.c>
RewriteEngine On
#force trailing slashes on real directories
RewriteCond %{REQUEST_FILENAME} -D
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L]
#use the directory viewer on directories without an index page
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ /myphp.php?url=%{REQUEST_URI} [QSA,L]
</IfModule>
This line:
RewriteCond %{REQUEST_FILENAME} -D
Should have been:
RewriteCond %{REQUEST_FILENAME} -d
Don't bother with Mod Rewrite, there is a directive for it
<Location /some/path>
DirectorySlash On
SetHandler some-handler
</Location>
http://httpd.apache.org/docs/2.2/mod/mod_dir.html
Did you mean
RewriteRule ^(.*)$ $1/ [L]
instead?
I don't know about your approach. I would try something like
RewriteRule ^/(\S+)/?$ /myphp.php?url=$1
I've used this for rewriting before and it works:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^domain\.com
RewriteRule ^(.*)$ http://www.domain.com$1
RewriteRule ^/(\S+)/?$ /myphp.php?url=$1
Note that I didn't include the trailing slash in the first rule.
Also, I would advice you not to rely on .htaccess unless absolutely necessary. This is because the server will check for .htaccess files constantly. Using the httpd.conf file instead means apache will only load conditions and rules once. At least I was adviced to do so because of this.
Try this. It will add trailing slash to directory requests which don't have trailing slash.
<IfModule mod_rewrite.c>
RewriteEngine On
#use the directory viewer on directories without an index page
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*?)/?$ /myphp.php?url=$1/ [QSA,L]
</IfModule>