.htaccess RewriteRule makes the address bar url changes when there isn't an end slash - apache

I have an strange situation with .htaccess configuration.
I have a multidomain hosting, with one directory per each domain.
For example, I have:
http://www.domain1.com
http://www.domain2.com
and the following directory structure:
/domain1/
/domain1/index.php
/domain2/
/domain2/index.php
/domain2/subdirectory/
/domain2/subdirectory/index.php
and a .htaccess file with the following content:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/domain1/.*$
RewriteRule ^(.*)$ domain1/$1 [L]
RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/domain2/.*$
RewriteRule ^(.*)$ domain2/$1 [L]
all works as I like with one exception:
if I do:
http://www.domain2.com/subdirectory/
(with a slash at the end)
the content is showed propertly and the url on the address bar keep unchanged, but
if I do:
http://www.domain2.com/subdirectory
(without a slash at the end)
the content is showed properly but the url on the address bar is changed to:
http://www.domain2.com/domain2/subdirectory/
(notice the subdirectory name and a slash is appended at the end)
and I don't like the user see that change on the address bar, that's my problem

This is mod_dir and DirectorySlash interferring with the URI-file mapping pipeline. By default DirectorySlash is turned on, which makes it so when apache thinks a request is for a directory, and it's missing the trailing slash, then it 301 redirects to the URI with the trailing slash. There's a good reason for doing this because of a possible information disclosure security concern. If you don't allow for directory indexing, you could just turn it off:
DirectorySlash Off
And then Apache won't redirect to the trailing slash at all. Or you can do the redirecting yourself as part of the rewrite engine. The reason why your internally rewritten URL is exposed is because 2 modules are mangling the URI, mod_dir and mod_rewrite, and they're doing it without any awareness of each other. So the URI gets rewritten by mod_rewrite and then mod_dir comes along and says "this is a directory!", mangles the URI some more by adding a trailing slash and flags it for a redirect response. Eventually, what you get is a redirect with a mangled URI. By handling the redirect from within mod_rewrite, by the time it gets to mod_dir, everything's peachy.
These would need to be above your current rules
RewriteCond %{HTTP_HOST} ^(www\.)?domain1\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/domain1/.*$
RewriteCond %{DOCUMENT_ROOT}/domain1%{REQUEST_URI} -d
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
RewriteCond %{HTTP_HOST} ^(www\.)?domain2\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/domain2/.*$
RewriteCond %{DOCUMENT_ROOT}/domain2%{REQUEST_URI} -d
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]

Related

Forcing "/" on home page (index page)?

I am using this code for my redirects on my .htaccess file:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^allvalleytransportation.com [NC]
RewriteRule ^(.*)$ https://www.allvalleytransportation.com/$1 [L,R=301,NC]
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Force trailing slash
<IfModule mod_rewrite.c>
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
</IfModule>
It appears to resolve the "/" on my subpages, however my index page does not force a trailing slash.
If I type in allvalleytransportation.com and copy the URL from the browser it generates this:
https://www.allvalleytransportation.com/
This is correct, however on the browser window itself, it appears without the trailing slash. Please see screenshot below. Is this something to be concerned about or is this normal?
Here is a conversation I had with YOAST that may help explain further.
https://wordpress.org/support/topic/canonical-issue-15/#post-15921609
An absolute URL with no path is the same as one with the path /.
If you type http://example.com or http://example.com/ into a browser's address bar, it will ask for /.
The difference is only in what is displayed in the browser's address bar.
(The same applies to any other client, only it might not have a visible address bar).

Apache .htaccess: Redirect to an URL containing a hashtag

The URLs
https://example.com/moved/
https://www.example.com/moved/
should be redirected to the URL
https://my.example.com/#views/settings.php?id=2
via .htaccess.
This is what I have tried:
RewriteCond %{HTTP_HOST} ^example.com
RewriteCond %{REQUEST_URI} moved$
RewriteRule (.*)$ https://my.example.com/#views/settings.php?id=2 [R=301,L]
However it seems not to work. I guess the reason is the #hashtag within the URL where I want to redirect to (it marks a comment within .htaccess).
How to redirect this correctly?
Change your rule to this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?example\.com$ [NC]
RewriteRule ^moved/?$ https://my.example.com/#views/settings.php?id=2 [R=301,L,NE,NC]
^(?:www\.)?example\.com$ will match www.example.com and example.com
Flag NE is used for no escaping of # in redirected URL
Pattern moved/?$ matches /moved/ and /moved, thus making trailing slash optional.
Make sure to clear your browser cache or use a new browser for testing.

how to redirect subdomain to subdir with .htaccess without changing URL

There is a domain/subdomain example.com/www.example.com (obviously they both point to /public_html) and website placed in this dir works perfectly. I've created subdir /public_html/wwwnew, and subdomain wwwnew.example.com. I want this subdomain to point to this subfolder, but I don't want to change URL typed by user (wwwnew.example.com). Of course I need to use .htaccess.
My current .htaccess file:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(wwwnew.)?example.com$
RewriteRule ^(/)?$ wwwnew [L]
RewriteBase /
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*) index.php [L]
Currently when I type in wwwnew.example.com URL changes to wwwnew.example.com/wwwnew. I want this /wwwnew to disappear...
Any help?
RewriteRule ^(/)?$ wwwnew [L]
If wwwnew is a physical subdirectory (which you say it is) then you should append a trailing slash on the end of the RewriteRule susbtition (and preferably the index document as well). If you don't then mod_dir will append the slash for you (in order to "fix" the URL) and in doing so triggers an external 301 redirect (which you appear to be seeing). Although this would be a redirect to wwwnew.example.com/wwwnew/ (with a trailing slash), not wwwnew.example.com/wwwnew as you've stated in the question.
RewriteCond %{HTTP_HOST} ^(wwwnew.)?example.com$
However, your condition rewrites requests for both the apex domain and the subdomain. In your description you only describe rewriting from the subdomain, not the apex domain (in which you have another site).
So, try the following instead:
RewriteCond %{HTTP_HOST} ^wwwnew\.example\.com
RewriteRule ^$ wwwnew/ [L]
There's no need for (/)? in .htaccess. Although, preferably, you should rewrite directly to the document (ie. index document) that you want to handle this request (otherwise mod_dir must do this for you). For example:
RewriteRule ^$ wwwnew/index.php [L]
You will need to clear your browser cache, as the erroneous redirect to /wwwnew will have been cached by the browser.
UPDATE:
However, the above only rewrites requests for the bare subdomain, without any URL-path (as stated in the question). In order to rewrite any requests for this subdomain (eg. wwwnew.example.com/<something>) to the subdirectory then you would need to do something like the following instead:
RewriteCond %{HTTP_HOST} ^wwwnew\.example\.com
RewriteRule !^wwwnew/ wwwnew/index.php [L]
This ensures we don't get a rewrite loop.

.htaccess applies only to root, while I need it to work across the domain name

I have the following ReWrite Rule
RewriteCond %{REQUEST_URI} !/maintenance.php$ [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif) [NC]
RewriteCond %{REMOTE_ADDR} !{developer_ip}
RewriteRule .* /maintenance.php [R=302,L]
This .htaccess should redirect all requests to the maintenance.php, except the requests coming from {developer_ip} which is my own ip address.
Problem:
The above rules work, but when I click on any of the internal links, it again shows me maintenance.php (which due to the IP rule, must not happen) which ends in either a index.php?{some_query} or a URL which is also already rewritten by the .htaccess itself, such as /Page/About-US (which originally is index.php?page_id=200.
Now I want the .htaccess to redirect all requests to maintenace.php (which already is doing) but no the requests coming from {developer_ip}. The above rules are fine, except the part excluding my own ip address, which redirects me for the internal links.
Perform an internal rewrite to maintenance page and keep your rules in this order:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(jpe?g?|png|gif)$ [NC]
RewriteCond %{REMOTE_ADDR} !{developer_ip}
RewriteRule !^maintenance\.php$ /maintenance.php [NC,L]
# skip any requests alredy rewritten to maintenance.php
RewriteRule ^maintenance\.php$ - [NC,L]
# rest of your rewrite rules

URL redirected to subdirectory Apache

I have a www root document which contains some subdirectories, where I want to route my requests conditionally to the domain requested.
For example. If the domain requested is testsite.com the Apache server should run the contents of the subfolder /testsite.com. If the domain requested is testiste.org Apache should run the /testsite.org folder.
Actually my .htaccess is:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?oliotarcento\.com$ [NC]
RewriteRule ^(.*)$ /oliotarcento.com/$1 [L]
In that case the rule works fine but not at all.
This is a curious case:
http://www.oliotarcento.com/forum/ works fine, but if I omit the trailing slash like http://www.oliotarcento.com/forum my browser will be redirected to http://www.oliotarcento.com/oliotarcento.com/forum/.
What I'm wrong?
It is happening because forum is a directory and mod_dir adda a trailing slash to redirected URL. Try this:
DirectorySlash Off
RewriteEngine on
RewriteBase /
# add a trailing slash to directories
RewriteCond %{DOCUMENT_ROOT}/oliotarcento.com/$1 -d
RewriteRule ^(.*?[^/])$ %{REQUEST_URI}/ [L,R=302]
RewriteCond %{HTTP_HOST} ^(www\.)?oliotarcento\.com$ [NC]
RewriteRule ^((?!oliotarcento\.com/).*)$ oliotarcento.com/$1 [L,NC]