.htaccess rewrite directories with index.html to subdirectory - .htaccess

At the site were some directories with html files like:
site.com/folderone/index.html
site.com/foldertwo/index.html
and it was available by links like:
site.com/folderone
site.com/foldertwo
now all these directories moved to /old-pages:
site.com/old-pages/folderone/index.html
site.com/old-pages/foldertwo/index.html
but old links should be available, so .htaccess file:
RewriteEngine on
RewriteRule ^folde(.*)$ /old-pages/folde$1 [L]
it's rewrite correct site.com/folderone/ and site.com/folderone/index.html
the problem is: for site.com/folderone it's not rewrite but redirect to site.com/old-pages/folderone/

The redirect is probably happening because of mod_dir and the DirectorySlash directive, which redirects requests for a directory that is missing the trailing slash so that the trailing slash is there. There's a good reason why that happens, as there's a info disclosure security concern without the trailing slash.
What you can do to avoid the redirect is either turn it off (not recommended):
DirectorySlash Off
or include the slash via mod_rewrite so that the two modules won't interfere with each other over the same request:
RewriteRule ^folder([^/]+)$ /folder$1/ [L,R=301]
You must add that before your other rewrite rules so that it gets applied first. Then your other rule should work.

Related

.htaccess: ??/index.php --> ??/, built on a relative path

Remove indx.php from URL; always redirect ??/ from ??/index.php
...including subdirectories, which may have their own .htaccess and index.php.
I'm using Apache with .htaccess.
I have a webapp with index.php in a subdirectory of the domain, say here:
example.tld/somedir/
But, it could be installed to any directory, such as these...
example.tld/anotherdir/
sub.domain.tld/
another.tld/
Each has its own index.php and its own .htaccess, for our purposes
On example.tld/somedir/: example.tld/, sub.example.tld/, et cetera also have their separate index.php and .htaccess, for their separate purposes
I need this to still work if placed in a subdir example.tld/dir/ of a WordPress or October or SuitCRM installation at example.tld/.
Always hide index.php via .htaccess
I want to make sure that:
All above four / (root) addresses link to index.php in whatever same directory.
index.php always redirects to / (root)
Examples
example.tld/anotherdir/index.php -> example.tld/anotherdir/
sub.domain.tld/index.php -> sub.domain.tld/
another.tld/index.php -> another.tld/
I need something like this
RewriteRule ^.*$ /{$PWD}/index.php [L,QSA]
...and any Rewrite statements that must precede it.
These Questions do not provide an answer:
htaccess redirect index.php to root (including subdomains)
This does not address subdirectories, only subdomains
This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/
htaccess remove index.php from url
This only removes indx.php from example.com/index.php/dir/subdir
This does not remove index.php from example.com/dir/index.php like I need
.Htaccess redirect index.php
This never got a working Answer
This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/
Redirect to index.php of .htaccess dir
This requires to specify /dir/, which I can't do.
This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/
The Answers don't work for the OP.
htaccess remove index.php and index.php/
This removes subdirectories from the URL also.
Redirect all to index.php using htaccess
This also requires to specify /dir/ in example.tld/dir/index.php
Answer is: RewriteRule ^.*$ /mvc/index.php [L,QSA], which I can't use.
.htaccess - simple redirect: index (with no extension!) / index.html / index.php to root
Does not address subdirectories, which I need.
Removing index.php from URLS with .htaccess
This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/
To serve index.php from the requested directory you use mod_dir's DirectoryIndex directive (which is probably already set in the server config, although defaults to index.html only) - you do not need mod_rewrite for this. For example:
# Serve "index.php" from the requested directory
DirectoryIndex index.php
This instructs Apache to serve index.php from whatever directory is requested. eg. Request /foo/bar/ then /foo/bar/index.php is served via an internal subrequest (no redirect). If index.php is not present in that directory you'll get a 403 Forbidden response (assuming directory listings - as generated by mod_autoindex - are disabled).
To remove index.php from any URL that is requested directly you can use mod_rewrite. For example:
RewriteEngine On
# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.+/)?index\.php(/|$) /$1 [R=301,L]
The above will redirect as follows, preserving the requested protocol and hostname:
/index.php to /
/foo/index.php to /foo/
/foo/bar/index.php to /foo/bar/
/fooindex.php - NO REDIRECT (404 expected)
/foo/index.php/bar (containing path-info) to /foo/ (path-info removed)
/foo/index.phpbar - NO REDIRECT (404 expected)
The (optional) capturing group (.*/)? contains the part of the URL-path before index.php. This is then available in the substitution string using the $1 backreference. In the case when /index.php is requested in the document root, this is empty. When a subdirectory is present then this contains a string of the form subdir/, including the trailing slash.
If you have no other directives in your .htaccess file then you don't strictly need the condition that checks against the REDIRECT_STATUS environment variable. This condition ensures that only direct requests are redirected in the case when you have a front-controller pattern later in the file that might rewrite requests to index.php.
If you do have other directives in the file then the order can be important. This rule that removes index.php via an external redirect must go before any existing rewrites, near the top of the file.
Note that this removes index.php from the URL regardless of whether the requested URL actually maps to a real file or whether the preceding URL-path even exists as a physical directory. So, /<something>/index.php is redirected to /<something>/ regardless of whether /<something>/ is a physical directory or not. This check can be implemented at the cost of an additional filesystem check - but it's probably not required.
NB: Test first with a 302 (temporary) redirect to avoid potential caching issues. Only change to a 301 (permanent) redirect once you have tested that it works as intended.
UPDATE#1:
These Questions do not provide an answer:
htaccess redirect index.php to root (including subdomains)
This does not address subdirectories, only subdomains
This redirects example.tld/dir/index.php to example.tld/, but I need example.tld/dir/
Actually, the first question you've linked to does answer your question, with regards to removing index.php from the requested URL. It does address subdirectories and would redirect example.tld/dir/index.php to example.tld/dir/ (not example.tld/ as you've stated).
The part of the question that discusses subdomains is a bit misleading as it doesn't really have anything to do with subdomains specifically.
The solution presented in the linked question basically does the same sort of thing as I've done above, except that it arguably matches too much (and not enough). It would incorrectly/unnecessarily redirect /fooindex.php to /foo (no trailing slash) and would fail to redirect URLs that contained path-info (which could be malicious). eg. /foo/index.php/bar would fail to redirect but still serve the contents of /foo/index.php (unless AcceptPathInfo had been disabled). Although whether these "errors" would actually cause an issue in your case is another matter.
UPDATE#2:
I have the code exactly in the directory for example.tld/dir
The code above assumes the .htaccess file is located in the document root. If the .htaccess file is located in the directory of where the app is installed then you would need to modify the above like so:
# Remove "index.php" from any URL and redirect back to the "directory"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{REQUEST_URI} ^/(.+/)?index\.php
RewriteRule (^|/)index\.php(/|$) /%1 [R=301,L]
The %1 backreference (as opposed to $1) refers to the captured group in the preceding CondPattern. This naturally includes the full URL-path, so avoids having to hardcode the directory in which the .htaccess file is located.
This applies to the directory that contains the .htaccess file and any subdirectories thereof. Note that, by default, this completely overrides any mod_rewrite directives that might be present in the parent .htaccess file (mod_rewrite directives are not inherited by default).
...including subdirectories, which may have their own .htaccess and index.php.
If additional sub-subdirectories have their own .htaccess file then this may or may not work depending on the directives used in these sub-subdirectory .htaccess files and/or how mod_rewrite inheritance is configured.
mod_rewrite directives do not inherit by default. So, if the .htaccess file in the sub-subdirectory enables the rewrite engine then the above mod_rewrite directives in the parent directory will be completely overridden (they are not even processed).
If, on the other hand, the .htaccess file in the sub-subdirectory uses directives from other modules then this may not be an issue.

Remove Trailing Slash With .htaccess

I've looked at 5 pages of Google, and StackOverflow, and I can't seem to find a way to remove the trailing slash on my domain using .htaccess. It uses Litespeed. Can anyone provide me with code I can add to my file? I'll reply to say whether or not it worked. Thanks!
they're physical directories.
You can't "simply" remove the trailing slash from physical filesystem directories. And I would recommend against trying to do so.
This is very different to trailing slashes on arbitrary "virtual" URLs that do not map to physical file-paths.
The trailing slash on directories is required by Apache to be able to correctly serve the DirectoryIndex document (mod_dir) and generate directory listings (mod_autoindex).
By default mod_dir explicitly appends the trailing slash to directories (if omitted) by issuing a 301 (permanent) redirect which is cached persistently by the browser.
In order to remove the trailing slash on directories (or prevent it from being appended) you need to override this default behaviour. But you must then manually append the trailing slash with an internal rewrite, so the URLs work as intended.
It is relatively trivial to prevent mod_dir appending the trailing slash:
# Prevent mod_dir from appending trailing slashes to directories
DirectorySlash Off
# Prevent mod_autoindex generating directory listings
Options -Indexes
Ensuring that directory indexes are disabled is an additional security measure when DirectorySlash Off is set, since without a trailing slash the presence of a DirectoryIndex document does not prevent mod_autoindex from generating a directory listing and exposing your file structure.
However, you now need to issue internal rewrites to "silently" append the trailing slash if a physical directory is requested without, for example:
# Append trailing slash on directories with an internal rewrite
RewriteCond $1 !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) $1/ [L]
Having implemented the above you should already be requesting URLs/directories without the trailing slash. However, if you are changing this behaviour and the URL with the trailing slash has been indexed by search engines or linked to by third parties then you also need to implement an external redirect to remove the trailing slash in order to preserve SEO. For simplicity, I assume you would want to remove the trailing slash from all URLs (not just physical directories).
For example, the following would need to go before the above rewrite:
# Remove trailing slash if requested directly
# NB: Applies to ALL URLs, including directories
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ /$1 [R=301,L]
The condition that checks against the REDIRECT_STATUS environment variable is required in order to prevent a redirect loop. We only want to redirect direct requests from the client and not rewritten requests by the later rewrite.
NB: Test with 302 (temporary) redirects to avoid potential caching issues.
You will need to clear your browser (and any intermediary) caches before testing.
However, as I noted at the top of my answer, unless you have a good reason for doing this then I would recommend against implementing this as you could encounter unexpected conflicts. At the end of the day, Apache needs that trailing slash on physical filesystem directories.
Aside:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
This removes the trailing slash from an arbitrary URL-path. This is your "standard" slash removal rule. However, this will not remove the trailing slash from physical directories, as you are trying to do. For two reasons:
The condition explicitly checks that the request does not map to a physical directory.
Removing the slash from a physical directory without first setting DirectorySlash Off will result in a redirect-loop since mod_dir will naturally try to append it again.
You can remove the trailing slash on your URL’s with the following in your .htaccess:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
For your testing, i’d recommend using R=302 so it’s not a permanent redirect as some browsers will cache these indefinitely without a full cache clear and in prod use R=301.

Would need to redirect with .htaccess from folder to file

I want to do a particular redirect
/mytag
redirect to file.php
the thing is it can be either /mytag/ or /mytag only without the final slash.
can't find this.. thanks
tried with this:
RewriteEngine on
options +FollowSymLinks
RewriteRule ^mytag(.*)$ file.php
As long as you don't have a file or directory called "mytag", then you can just end the regex with /? to make the ending slash optional:
RewriteRule ^mytag/?$ file.php [L]
Though what you already have should allow both the slash or no slash at the end. This won't work if you have a directory called mytag because mod_dir and DirectorySlash will always redirect a request for a directory that doesn't have a trailing slash to the same request with the trailing slash. If you have Multiviews turned on, and you happen to have a mytag.php (or something similar), mod_negotiation will kick in and the rewrite rule will get ignored.

My url rewrite redirects to mydomain.com/var/www/clients/client3/web25/

I'm trying to make a rewrite of a url on my joomla site. I have an extra page in there wiht some other stuff on it.
I have:
RewriteRule ^company/([^/]+) company?alias=$1 [NC]
where i want company/somecompany to show what the url company?alias=somecompany will give (not forward to it).
What i get instead is a redirection to:
http://www.mydomain.dk/var/www/clients/client2/web5/web/company?alias=somecompany
Also if i include a "-" like "company/some-company" it skips my rewrite and just goes to the joomla rewrite rules (and can't find the article)
What am I doing wrong?
You need to add a RewriteBase. When your rewrite rule's target doesn't start with a leading slash (making it an absolute URI), apache needs to guess whether it's a URI-path or a file-path, and it is incorrectly guessing that it's a file-path. Adding a base tells apache that it's a URI path.
RewriteBase /
or add a leading slash to your target: /company/?alias=$1
You also want to add a trailing slash to company and use the [L] flag:
RewriteRule ^company/([^/]+) company/?alias=$1 [L,NC]
The missing trailing slash may be the culprit that's causing mod_dir and DirectorySlash redirecting. And the L flag may be why the joomla rules are eventually getting applied.
Here is the working example:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteRule ^/?old-folder/(.*)$ /new-folder/$1 [R=301,L]
</IfModule>
For more examples, check:
Learn Apache mod_rewrite: 13 Real-world Examples
Apache Conf Snippets for VS Code

htaccess rewrite rules for directories

I am having trouble with some rewrite rules on an updated site...I am trying to redirect requests for old directories to new pages, like this:
http://www.mysite.com/olddirectory --> http://www.mysite.com/this-is-the-new-page
the following rule works, but not with a trailing slash on the directory:
ie: /olddirectory redirects correctly, but /olddirectory/ doesn't
RewriteRule ^olddirectory$ this-is-the-new-page [R=301,NC,L]
Any ideas on how to get it to recognise the trailing slash on the dir?
The following rule will do redirect with or without trailing slash:
RewriteRule ^olddirectory/?$ /this-is-the-new-page [NC,R=301,L]
The key is to make trailing slash optional, and that's what ? does: /?

Resources