Trail slash with multiple htaccess - .htaccess

I have directory structure like this:
public_html
.htaccess[1]
-apps
-.htaccess[2]
-admin
-myviwo
when I request http://localhost/mysite/admin it redirect me to http://localhost/mysite/apps/admin/ and shows me the content of the admin directory, if I request http://localhost/mysite/admin/ it doesn't redirect me but it shows me the content of admin directory again which is correct. But I want:
http://localhost/mysite/admin
http://localhost/mysite/admin/
Both of the above URLs shows me the content of admin directory without redirecting me.
.htaccess [1]
RewriteEngine On
RewriteBase /
RewriteRule (.*) apps/$1 [L]
.htaccess [2]
RewriteEngine On
RewriteBase /
RewriteRule ^admin/?(.*)$ admin/$1 [L]
RewriteRule ^(.*)$ myviwo/$1 [L]
How can I achieve this?

In the admin directory, add an htaccess file with the following:
DirectorySlash Off
This makes it so mod_dir won't redirect requests for the directory admin. However, note that there's an important reason why directory slash is "on" by default:
Security Warning
Turning off the trailing slash redirect may result in an information disclosure. Consider a situation where mod_autoindex is active (Options +Indexes) and DirectoryIndex is set to a valid resource (say, index.html) and there's no other special handler defined for that URL. In this case a request with a trailing slash would show the index.html file. But a request without trailing slash would list the directory contents.
If that's ok with you, then that's all that you need.
Otherwise, you may need to add a special rule specifically for admin. In the .htaccess[1] file, add right below the rewrite base:
RewriteRule ^admin$ apps/admin/ [L]
EDIT: to make the above rule dynamic, you need to first check if it's a directory:
RewriteCond %{DOCUMENT_ROOT}/apps%{REQUEST_URI} -d
RewriteRule ^(.*[^/])$ apps/$1/ [L]

Related

mod_rewrite existing directory changes URL in address bar

I'm trying get mod_rewrite to redirect all requests that aren't files to index.php so I can handle routing for clean URLs.
<IfModule mod_rewrite.c>
RewriteEngine On
# Route requests to index.php for processing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?request=$1 [QSA,L]
</IfModule>
For some reason, when I access an existing directory without a trailing slash, the address bar is reformed to include a trailing slash and the query string, which is not very clean.
I'm able to improve this by changing the RewriteRule to ^(.+)/$ and adding RewriteBase /. However, this directs all URLs to one with a trailing slash. Not a big deal, but not how I want it.
If, for example, /test/folder exists and I go to that directly, I'd like the address bar to display that, instead of displaying /test/folder/ or /test/folder/?request=/test/folder.
I'd give this a try:
DirectoryIndex index.php
<IfModule mod_rewrite.c>
RewriteEngine On
# I tested this inside a subdir named "stack", so I had to uncomment the next line
#RewriteBase /stack
# Route requests to index.php for processing
# Check if the request is NOT for a file:
RewriteCond %{REQUEST_FILENAME} !-f
# Check if the request IS for an existing directory:
RewriteCond %{REQUEST_FILENAME} -d
# If all criteria are met, send everything to index.php as a GET request whose
# key is "request" and whose value is the entire requested URI, including any
# original GET query strings by adding QSA (remove QSA if you don't want the
# Query String Appended):
RewriteRule .* index.php?request=%{REQUEST_URI} [R,L,QSA]
</IfModule>
If this doesn't happen to work, please let me know what else is in your .htaccess file because for the most part, it looks like it should be working. Should. ;)
Well, persistence pays off. jerdiggity's answer provided insight, which led to further experimentation and research. Eventually, I came to the conclusion that there must be something built into Apache that is rewriting the trailing slash.
As jerdiggity suspected, all of the Rewrite logic was accurate, but something called a DirectorySlash Directive in another directory-related Apache module, mod_dir, was adding the trailing slash.
Apparently, you can simply disable this directive, which I added to the top of my logic:
DirectorySlash Off
RewriteEngine On
...

301 Redirect entire site to new directory except for index.html landing page

The wordpress site I'm working on got moved into a subdirectory therefore all the links from other sites don't work anymore. I implemented a 301 redirect with .htaccess which is great because it fixes that problem BUT the old root directory now has an index.html that has landing page my client absolutely wants to be seen.
So, how can I set up my .htaccess to redirect all traffic into the sub directory (to fix the incoming links) EXCEPT the index.html in the root directory because it has the landing page.
I don't know how htaccess works well but this is what I have right now.
Order deny,allow
ErrorDocument 404 /404.php
DirectoryIndex index.php index.html
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/$ [OR]
RewriteRule ^.*$ http://example.com/portal/$0 [R=301,L]
Thanks!!
Edit for clarification:
Right now EVERYTHING redirects from the root to the subdirectory. I want everything to redirect except for index.html in the root directory. If the user requests just the domain name (http://example.com) without specifying a page, I also want him/her to be served up the index.html page in the root directory.
The following code does what you are asking for: "if the request does not match either index.php or index.html or "/" (i.e. nothing) (and the match is not case sensitive) then serve up the alternate location"
Order deny,allow
ErrorDocument 404 /404.php
DirectoryIndex index.php index.html
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index\.(php|html) [NC]
RewriteCond %{REQUEST_URI} !^/$ {NC]
RewriteRule ^.*$ http://example.com/portal/$0 [R=301,L]
I have tested this using the excellent online testing tool http://htaccess.madewithlove.be
Using the following test cases:
http://example.com -- no rewrite, second condition not met
http://example.com/ -- ditto
http://example.com/index.html -- first condition not met
http://example.com/index.php -- first condition not met
http://example.com/some/page.html -- rewritten as http://example.com/portal/some/page.html
EDIT You said that this still didn't work quite as expected; so I brought out the big guns. By turning on "maximum logging" of everything that the rewrite engine does with the directives
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 9
(pick any path you want, obviously), then looking at the end of the logfile in a terminal window with
tail -f /var/log/apache2/rewrite.log
You can quickly see where things are not working quite right. A bit of fiddling led me to the following code. It says "if the requested URI is just /index.html or /index.php, or if it starts with /portal, or if it is blank, then don't redirect.
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/index\.(php|html) [NC]
RewriteCond %{REQUEST_URI} !^/portal.*$ [NC]
RewriteCond %{REQUEST_URI} !^/$ [NC]
RewriteRule ^(.*)$ http://example.com/portal$0 [R=301,L]
The test cases worked for me - see if they work for you!
NOTE: I made these changes in the httpd.conf file, not in the .htaccess file of the root directory. You need to be careful to make it so the .htaccess file in the root directory is even read - the default Apache configuration has an Override none for that directory, so some extra work is needed. By putting this configuration change in the httpd.conf file (and issuing a sudo apachectl restart command) you avoid the difficulty. Depending on who is hosting your website, and what control you have, that may not be an option for you. There may come a point where the experts for this problem can be found on superuser.com rather than SO... but I'm hopeful this does the trick for you.

htaccess redirect if filename equals something

I'd like to set a redirect (preferably with RewriteCond) so that if the requested file is index.php regardless of directory, it will be redirected to another site.
So visiting /index.php or/files/index.php or /stuff/index.php (etc.) will all redirect you to another domain.
Here is a general way to do it. This rule set should be placed in the .htaccess file in the root directory:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} index\.php/? [NC]
RewriteRule .* http://otherdomain.com/ [R=301,L]
Redirects permanently any URL that holds index.php in any position, like
http://mydomain.com/index.php or
http://mydomain.com/any/folder/quantity/index.php or
http://mydomain.com/any/folder/quantity/index.php/any/folder/quantity/
To
http://otherdomain.com/
That's it. You don't explain much so nothing is passed to the other domain, just as you say in your question:
...redirected to another site.
These rules should do it (when placed inside /.htaccess file):
RewriteEngine On
RewriteRule (?:^|/)index\.php$ http://otherdomain.com/ [R=301,L]

.htaccess rewriterule - check for referrer, if wrong referrer send to a specific URL, if right, allow directory to be read

I have a folder on my site (domain.com/protect) I want to limit to only one referrer (otherdomain.com/subfolder).
Deny for all others, allow only if coming from that URL.
If not coming from that URL, then redirect the visitor over to otherdomain.com/login instead.
How would I write that out in .htaccess rewrite rules?
In the htaccess file in your /protect directory, add these rules:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !otherdomain\.com/subfolder
RewriteRule ^ - [L,F]
The condition checks that the referer doesn't contain: otherdomain.com/subfolder, and if it doesn't, then whatever the request is (inside the /protect directory) will result in a 403 Forbidden.
Alternatively, you can put these rules in the htaccess file in your document root if you would rather keep everything in once place:
RewriteEngine On
RewriteCond %{HTTP_REFERER} !otherdomain\.com/subfolder
RewriteRule ^/?protect/? - [L,F]

Rewriten URL without trailing slash?

RewriteEngine on
RewriteRule ^$ http://my-site.com/directory [R=301,L]
This redirects my root page to
http://my-site.com/directory/
(notice the trailing slash).
How can I make .htaccess omit the trailing slash when generating the URL?
This is because directory is an existing directory, this is not a rewritten url.
Use another word instead of :
RewriteEngine on
RewriteRule ^$ /mypath [R=301,L]
RewriteRule ^mypath$ /directory/ [L]
Quote from noupe.com :
The filesystem on your server will always take precedence over the
rewritten URL. For example, if you have a directory named “services”
and within that directory is a file called “design.html”, you can’t
have the URL redirect to “http://domain.com/services”. What happens is
that Apache goes into the “services” directory and doesn’t see the
rewrite instructions.
To fix this, simply rename your directory (adding an underscore to the
beginning or end is a simple way to do that).
Bonus : To remove trailing slash in every urls :
RewriteEngine On
RewriteRule ^(.*)/$ $1 [R,301,L]

Resources