How do I write a mod_rewrite so that it doesn't affect a subdomain that is in a subfolder - apache

I have a site where the frontend is on the main domain and the backend is on a subdomain whose document root is a subfolder of the main domain's document root.
I have added this:
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
to the .htaccess file for the main domain because it was giving a 404 error for refreshes and direct access. The problem is that adding that config results in a 500 error on my backend. How can I solve this?

You shouldn't necessarily need to do anything with regards to the subdomain, depending on the type of requests you are making (which you've not stated).
However, you can disable mod_rewrite for the subdomain by creating an additional .htaccess file in the root of the subdomain (ie. in the subfolder off the main domain's document root) and place the following:
# /subfolder/.htaccess (subdomain)
RewriteEngine Off
.htaccess files are inherited along the filesystem path, so the .htaccess file in the root of the main domain will certainly be processed when accessing the subdomain, except that the conditions (RewriteCond directives) should already exclude any requests for actual files/directories.

So it turns out I only needed to add one line to exclude the affected subdomain.
RewriteCond %{HTTP_HOST} !example\. [NC]
That did the trick.

Related

Apache 2.4 .htaccess - Point All Requests to index.html With One Exception

I currently have the following .htaccess:
<IfModule mod_rewrite.c>
Options Indexes FollowSymLinks
RewriteEngine On
RewriteBase /production/
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
The web server's document root is currently the /production folder referenced in the above (the .htaccess file is in the parent folder since /production is deleted and rebuilt with every code commit). The above will direct all traffic to my site to index.html.
I would like to make an exception to this. If the request is www.mydomain.com/specialrequest, I would like a PHP script called script.php in the parent folder to run.
To review, this is my /var/www/html directory:
-html
-production
-anotherfolder
-.htaccess
-script.php
Apache is pointing to /var/www/html/production and I would like all requests to go to the index.html file in that directory unless the request is /specialrequest - in which case, I would like script.php to run.
Apache is pointing to /var/www/html/production
So, /var/www/html/production really is defined as the DocumentRoot. And so your .htaccess file is located above the document root. And the file you want to rewrite to (upon receiving this special request) is also above the document root.
Unfortunately, you can't rewrite to a file that is above the document root using .htaccess (regardless of where that .htaccess file is located). This is because the RewriteRule substitution in per-directory .htaccess files takes a URL-path, so trying to rewrite to a URL above the document root is simply invalid. If, however, you had access to the server config (or virtual host) then you could rewrite to a filesystem path (including above the document root) - instead of a URL-path - using this method.
So, script.php would need to be within the document root in order to be able to do this using .htaccess. In which case, you could do something like:
RewriteEngine On
# Exception
RewriteRule ^specialrequest$ /script.php [L]
# Front controller
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
But in this case, script.php is would need to be located at /html/production/script.php (in the document root), not at /html/script.php (above the document root) - as in your current filesystem structure.
Incidentally, the RewriteBase /production/ directive in your .htaccess file is entirely superfluous. You're not using a relative path substitution anyway, but since /production is the document root then /index.html (a document root relative URL-path) will rewrite to /production/index.html anyway.
If, however, you could write this directly in your server config (or virtual host), then you could do what you require. For example:
RewriteEngine On
# Rewrite to filesystem path (in the server config)
RewriteRule ^/specialrequest$ /var/www/html/script.php [L]
# Front controller
RewriteRule ^/index\.html$ - [L]
RewriteCond %{LA-U:REQUEST_FILENAME} !-f
RewriteCond %{LA-U:REQUEST_FILENAME} !-d
RewriteRule ^/. /index.html [L]

www I added to HTTP_HOST via htaccess file disappears when redirecting to second htaccess file

I am struggling with an htaccess file. Actually, it is two files.
But first things first, so my questions are:
1) Why does my .htaccess(1) file add the www at the beginning of the HTTP_HOST and the slash at the end of folder REQUEST_URI IF AND ONLY IF the .htaccess(2) file is not there (deleted or renamed)?
2) What is wrong with the RewriteRule and conditions that I wrote in .htaccess(2) to redirect the REQUEST_URI to /publicfolder/REQUEST_URI? Conditions doesn't seem to work and when I surf to domain.com/nonpublicfolder it goes to domain.com/domainfolder/publicfolder/nonpublicfolder.
My website is structured as follows:
/
.htaccess(1)
domainfolder/
.htaccess(2)
publicfolder/
genericfolder/
index.extention
file.extention
nonpublicfolder/
So I have one htaccess file in the root folder ( .htaccess(1) ) where I:
add 'www' at the beginning of the HTTP_HOST;
add '/' at the end of REQUEST_URI if it does not end with a file extension;
redirect domain.com/anyfolder/anyfile.extention to domain.com/domainfolder/anyfolder/anyfile.extention;
like so:
<IfModule mod_rewrite.c>
# System symbolic links are allowed.
Options +FollowSymlinks
# Runtime rewriting engine enabled.
RewriteEngine On
# HTTP_HOST starts with 'www'.
RewriteCond %{HTTP_HOST} ^(?!www\.) [NC]
RewriteRule ^.*$ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,NC]
# Folder requests end with '/'.
RewriteCond %{REQUEST_URI} ![^/]+\.[a-zA-Z0-9]+$ [NC]
RewriteRule [^/]$ %{REQUEST_URI}/ [R=301,NC]
# Files and folders are in the 'domainfolder' folder.
RewriteCond %{REQUEST_URI} !^/?domainfolder/ [NC]
RewriteRule ^.*$ /domainfolder%{REQUEST_URI} [R=301,NC]
</IfModule>
And then I have my .htaccess(2) file - in the domainfolder folder - where I redirect files and folders requests to the publicfolder folder IF AND ONLY IF they are not pointing to the notpublicfolder folder or to the Google Site Verification file:
<IfModule mod_rewrite.c>
# Runtime rewriting engine enabled.
RewriteEngine On
# Public files and folders are in the 'publicfolder' folder.
RewriteCond %{REQUEST_URI} !^/?domainfolder/publicfolder/ [NC]
RewriteCond %{REQUEST_URI} !^/?domainfolder/nonpublicfolder/ [NC]
RewriteCond %{REQUEST_URI} !^/?domainfolder/googlexxx.html$ [NC]
RewriteRule ^/?(.+)$ /publicfolder/$1 [R=301,NC,L]
</IfModule>
Thank you very much for your time and patience.
(1) mod_rewrite does multiple passes and on each by default it will only open the first .htaccess file it finds walking up the folder hierarchy from the requested file. read my Tips for debugging .htaccess rewrite rules for more discussion of this. Yes you can use a Options setting to change this behaviour but this has a performance hit and I would suggest that you avoid doing so.
(2) When using hierachical .htaccess files, mod_rewrite has to associate URI path to the current directory and can get this wrong. The RewriteBase directive tells mod_rewrite what the true association is, so use this.
Rule order is important. If you don't have a local Apache instance where you have root privilege and can enable rewrite logging, you need to build up your access file(s) incrementally rule-by-rule, testing at each step because you only get a work/doesn't work return. Again my tips explains how to do this.

Pointing subdomains to a "directory"

I have two questions regarding pointing subdomains to a directory:
Currently I run local, but I can run my site on a fake domain i have set up (with hosts file), its called mysite.com. How can i (by server settings?) do so All subdomains will point to / ? Example anders.mysite.com should show mysite.com and asdassdd.mysite.com also.
Maybe 1. is not necessary, but how do i by htaccess point anders.mysite.com to mysite.com/anders ? Important notice is that should not redirect.
Why i thought of 1. is because I do not want to specify anywhere in the htaccess or any apache/domain setting, what the subdomain are, since this will be dynamic (created by logged in users in my webapplication)
Currently the users can use mysite.com/anders/ which is a URI they have created, and not a real directory. In the Kohana bootstrap I am then grabbing the URI and showing the relevant user page.
I am using Kohana MVC framework and have this in my htaccess:
# Turn on URL rewriting
RewriteEngine On
# Installation directory
RewriteBase /
# Protect hidden files from being viewed
<Files .*>
Order Deny,Allow
Deny From All
</Files>
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]
Any help appreciated!
For 1, in your vhost just add a ServerAlias:
ServerAlias *.mysite.com
Then any subdomain (www included) will get pointed to the same document root.
If you want to put subdomains in their own directory (and since you have access to server config), you can use mod_vhost_alias and the VirtualDocumentRoot directive:
VirtualDocumentRoot /path/to/your/htdocs/%1
So if you request blah.mysite.com, you'll end up in /path/to/your/htdocs/blah as the doc root.
If it's a matter of you needing directory names of non-existent directories in the URI so that Kohana can route them, you'll need to make sure you have mod_proxy loaded:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTP_HOST} ^([^.]+)\.
RewriteCond %{REQUEST_URI} !^/%1/
RewriteRule ^(.*)$ /%1/$1 [L,P]
To proxy the request back to Kohana with the right URI.
how do i by htaccess point anders.mysite.com to mysite.com/anders ? Important notice is that should not redirect.
You can use this rule:
RewriteCond %{HTTP_HOST}:%{REQUEST_URI} ^([^.]+)\.[^:]+:(?!/\1/).*$
RewriteRule ^ /%1%{REQUEST_URI} [L]

htaccess rewriterule to send a file to another file in the same directory

I have a directory that contains an index.php and an index.html file, both being published from a CMS. There's a specific IP address that will attempt to access index.html, but should instead be shown index.php in the same directory. All other traffic should act as normal.
I've been working with some variations of this code:
RewriteEngine On
RewriteCond %{REMOTE_HOST} ^123\.456\.789\.10
RewriteRule ^index\.(htm|html?)$ index.php [NC,R=301,L]
This does do the redirect, but of course it goes to the root of the site rather than staying in the same directory. It's somewhat unclear what the directory path will be in all cases, so I'd like to tell Apache to stay in the same directory it's in.
Is this possible?
Thanks,
Jonathan
If you want to have this rule for IP: 123.456.789.10 then you shouldn't have this IP with
negation like: RewriteCond %{REMOTE_HOST} !
Try this code:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /subdir/
RewriteCond %{REMOTE_HOST} ^123\.456\.789\.10$
RewriteRule ^index\.html?$ index.php [NC,R=302,L]

.htaccess, Laravel & Ikonboard

I have to admit, creating mod-rewrite rules still confuses me! So, I'm after some help please...
I've taken on a site built in Laravel, but now need to add an existing forum into the domain. The forum is Ikonboard, which on the live site lives in the cgi_bin folder. When I copy this to the new site, I can't get access because the htaccess is rewriting ALL URL's to the public folder (where Laravel want's it).
So, how can I make any requests to the cgi_bin folder work as well as keeping the rewrite to public for Laravel?
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine On
# Rewrite to 'public' folder
RewriteCond %{HTTP_HOST} ^www.mydomain.com$
RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) public/$1 [L]
</IfModule>
Thanks
Simple:
RewriteCond {%REQUEST_URI} !^/cgi_bin
Add this above your other REQUEST_URI rule. If cgi_bin is in the URI, then it will stop rewriting.
Edit - Based on your response with regards to the directory structure, it seems to be wrong. Your www directory is your public directory. So, your structure should look like this:
/www/ (your public folder)
bundles/ (etc...)
cgi_bin/
.htaccess
index.php
/laravel/
(etc...)
Change your directory structure to look like that, and make sure that your .htaccess file has the following in it:
<IfModule mod_rewrite.c>
Options +FollowSymlinks -MultiViews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
If you call a CGI document, it should pass through because %{REQUEST_FILENAME} !-f is set above. All assets should pass through as well. You do not need to specify whether or not the cgi_bin folder is being requested. If it does not work, then add the line as I had originally in this answer (except, you would put the rule just under RewriteEngine On.