Generic .htaccess for multiple websites stored in subdirectories - apache

My development environment is set up for using a single host (localhost). I am developing multiple websites on my machine, each stored under its own directory like this:
/var/www/site1
/var/www/site2
...
The document root is set to /var/www on my machine.
I am using URL rewriting for most of these websites and most of the .htaccess files will rewrite a sub-directory to GET parameters in different ways like this:
http://localhost/site1/home/red -> http://localhost/site1/index.php?page=home&p1=red
http://localhost/site2/index/param1/param2/param3 -> http://localhost/site2/index.php?page=index&p1=param1&p2=param2&p3=param3
I also tend to copy some of these websites under different directories and, when I do that, I have to make a lot of changes in the .htaccess files for the website that I'm copying.
I would like to know if there is a way to define a constant that contains the website's root directory (not the host's document root) and how can that be used with the rewrite rule so that I would need to change only one line of code (setting this constant to a different value) when copying a website.
Putting this in a different form, is there a way to perform rewrites that relate to a website root instead of a host / %{HTTP_HOST} (i.e. the "host" for the website being localhost/site1 instead of localhost) and how can this be done?
I have tried removing the host from each request at the beginning of the script and prepending it back at the end of the script, but this does not work with rewrite rules that use the [L] option.
Thank you!
Regards,
Lucian

You could make an htaccess file with rules like this:
RewriteEngine On
RewriteBase /site1/
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+) index.php?page=$1&p1=$2&p2=$3&p4=$4 [L,QSA]
And put this in the directory /var/www/site1, and if you want for it to apply to site2, change the RewriteBase and put the rules in /var/www/site2.

Related

Howto use path/directory outside the domain root via symlink without access to domain config?

I am working an a shared hosting plattform which does not allow to edit or access the Apache config file.
The goal is to access the same files from two different domains which point to different domain roots:
test.example.com ---> /test_root/web
public.example.com ---> /public_root/web
Now I would like to access the same files using test.example.com/some/files/... and public.example.com/some/files/...
Of course I could simply copy the files to /test_root/web/some/files/... and to /public_root/web/some/files/... but this obviously just an example. In reality the files are a helpdesk system which should be integreated both into the test- and public-site. Copying the files would include maintaining two different systems, etc.
The goal is, to place the the files somewhere outside the two domain roots and make them available from both domains:
/test_root/web/some/files ---> /path/to/some/files
/public_root/web/some/files ---> /path/to/some/files
I created symlink to achive this (ln -s ...) but this does not work out. When I access on of the domains (e.g. test.example.com/some/files) I only get a blank page without any information what whent wrong.
I assume that the Apache is not configured to follow the symlinks. Without access to the Apache config I can neither check nor fix it.
Adding Symlinks to .../web/.htacess does not make any difference:
// test_root/web/.htaccess
Options +FollowSymLinks
So the question is: How can I make files outside the domain root available within a domain? Is this even possible? Is this possible using symlinks?
Add this in you .htaccess file.
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} test.example.com/path/to/files [NC]
RewriteRule ^(.*)$ http://public.example.com/path/to/files [R=301,NC]
Test out this code. /path/to/files must be under /public_root/web/.
Something like /public_root/web/path/to/files/

How can I have redirect or make an alias for my websites directories?

Real directory structure:
http://example.com/directory1/directory2/directory3/hiddendirectory/directory4/
I need the file to open as:
http://example.com/hiddendirectory/directory4/
in the browser, but in reality the directory still be in the first location.
I am on shared hosting with hostgator and do not have full privileges so I cannot run any scripts.
I've done some research and I've messed around trying create an alias, but I can't get anything to work.
Here is what I put in the .htaccess file:
Alias /hiddendirectory/directory4 /directory1/directory2/directory3/hiddendirectory/directory4
But I always get a 500 server error. Any advice would be appreciated.
Alias directive runs on the Server config context not in htaccess.
In htaccess you can use mod_rewrite to rewrite your dirs.
RewriteEngine On
RewriteRule ^hiddendir/dir4/?$ /dir1/dir2/dir3/hiddendir/dir4 [NC,L]
This will rewrite
/hiddendir/dir4/
to
/dir1/dir2/dir3/hiddendir/dir4

Domain handling with a controller

Im running an MVC based application on my mainsite, I have 2 other domains (for the sake of an example, www.a.com & www.b.com)
I'd like to be able to handle all a.com's requests with mainsite.com/a/ and similarly b.com with mainsite.com/b/
However I do not want the url to be redirected/changed in the browser.
I've been trying with mod_rewrite, however it seems to be clashing with my existing .htaccess rules set for mainsite.com
this is my existing .htaccess
Could anyone please suggest the best way to do this?
In the existing .htaccess, I don't see any rules redirecting the domains a.com or b.com. To do that is pretty straightforward, though.
A condition for selecting the proper host www.a.com or a.com
RewriteCond %{HTTP_HOST} ^(?:www\.)?a\.com$
prevent an endless loop
RewriteCond %{REQUEST_URI} !^/a/
and do the actual rewrite
RewriteRule ^ /a%{REQUEST_URI} [L]
As long as you don't use the R flag, the URL shouldn't change in the browser.
The rule for host b.com is analogous.
Update:
Since you already have a very large .htaccess file, the performance impact shouldn't matter too much. If you want to know for sure, there's no substitute for measuring.
If you want to reduce the performance hit nevertheless, you have two options
Move the directives in the .htaccess file to your main config or virtual config file, see When (not) to use .htaccess files for an explanation.
Do some custom rewriting with PHP in your front controller. This depends on the framework or routing mechanism you use, of course.

rewritemap for SEO and pretty URLs

I am attempting to redirect & rewrite some dynamic PHP URL's to pretty and SEO friendly URLs. I have manged to do this successfully through .htaccess with the following code:
RewriteCond %{QUERY_STRING} ^somevar=green&nodescription=([a-zA-Z0-9_-]*)$
RewriteRule (.*) /green\/%1\/? [L,R=301]
RewriteRule ^green/([^/]*)/$ /script.php?somevar=green&nodescription=$1&rewrite=on [L]
This creates a somewhat pretty URL as follows:
http://www.mysite.com/green/aA43-/
As I say, this works absolutley fine. Apart from one thing. The parameter nodescription contains a non-descriptive random set of letters, numbers and other characters.
I would like to rewrite the nodescription parameter to a more descriptive one. I understand that I can do this with a rewritemap through Apache. However, I have no experience at doing soemthing like this, and I'm not entirely sure where to start.
Normally I would simply alter script.php so that it contains more descriptive parameters, but this time I have no control over the script; I am pulling it from another site using cURL.
Can anybody give me an example of how to pull this off?
Thanks!
Matt
Well, to answer my own question, to pull this off you need access httpd.conf file on your apache server. My shared hosting company didn't allow access to this file (I doubt any would allow you access).
So I bit the bullet and purchased a VPS. I will post the steps I took here in order to set the rewritemap up in the hope that it will help a lost soul :) Ok, here goes...
My VPS has WHM installed, so in WHM I went to:
Server Configuration >> Apache Configuration >> Include Editor
Pre Virtual Host Include >> All Versions
This feature takes any text you put in and includes it in your httpd.conf file without worrying that it will be overwritten at a later stage. If you don't have WHM on your server then you can add the text directly to your httpd.conf file; make sure it is outside and before any virtual hosts.
OK, so I included the following map declaration and rewrite rule:
#Map to redirect (swaps key and value)
RewriteMap rwmap txt:/home/*/public_html/rdmap.txt
<Directory /home/*/public_html/test>
Options All -Indexes
RewriteEngine on
RewriteRule ^url/([^/]*)/$ /script.php?foo=${rwmap:$1|$1}&rewrite=on [L]
</Directory>
The actual map is a simple text file containing key/value pairs - you need to place this file in the directory declared in RewriteMap rwmap txt:/home/*/public_html/rdmap.txt.
And there you go. Apache now rewrites my URLs for me and I now have some nice and pretty SEO optimized links thanks to my rewrite map! Hoorah!
RewriteEngine on
RewriteRule ^green/([^/]*)/(.*)$ /script.php?somevar=green&nodescription=$1&rewrite=on [L]
This rewrite will allow you to pass "arbitrary text" that has nothing to do with the rewrite. For example:
http://www.mysite.com/green/aA43-/some-seo-boosting-title
Will still reroute correctly to script.php; the latter part will simply be ignored by the rewrite.

mod_rewrite to absolute path in .htaccess - turning up 404

I want to map a number of directories in a URL:
www.example.com/manual
www.example.com/login
to directories outside the web root.
My web root is
/www/htdocs/customername/site
the manual I want to redirect to is in
/www/customer/some_other_dir/manual
In mod_alias, this would be equal to
Alias /manual /www/customer/some_other_dir/manual
but as I have access only to .htaccess, I can't use Alias, so I have to use mod_rewrite.
What I have got right now after this question is the following:
RewriteRule ^manual(/(.*))?$ /www/htdocs/customername/manual/$2 [L]
this works in the sense that requests are recognized and redirected properly, but I get a 404 that looks like this (note the absolute path):
The requested URL /www/htdocs/customername/manual/resourcename.htm
was not found on this server.
However, I have checked with PHP: echo file_exists(...) and that file definitely exists.
why would this be? According to the mod_rewrite docs, this is possible, even in a .htaccess file. I understand that when doing mod_rewrite in .htaccess, there will be an automated prefix, but not to absolute paths, will it?
It shouldn't be a rights problem either: It's not in the web root, but within the FTP tree to which only one user, the main FTP account, has access.
I can change the web root in the control panel anytime, but I want this to work the way I described.
This is shared hosting, so I have no access to the error logs.
I just checked, this is not a wrongful 301 redirection, just an internal rewrite.
In .htaccess, you cannot rewrite to files outside the wwwroot.
You need to have a symbolic link within the webroot that points to the location of the manual.
Then in your .htaccess you need the line:
Options +SymLinksIfOwnerMatch
or maybe a little more blindly
Options +FollowSymlinks
Then you can
RewriteRule ^manual(/(.*))?$ /www/htdocs/customername/site/manual/$2 [L]
where manual under site is a link to /www/customer/some_other_dir/manual
You create the symlink on the command line with:
ln -s /www/htdocs/customername/site/manual /www/customer/some_other_dir/manual
But I imagine you're on shared hosting without shell access, so look into creating symbolic links within CPanel,Webmin, or whatever your admin interface is. There are php/cgi scripts that do it as well. Of course, you're still limited to the permissions that the host has given you. If they don't allow you to follow symlinks as a policy, you cannot override that within your .htaccess.
AFAIK mod_rewrite works at the 'protocol' level (meaning on the wire HTTP). So I suspect you are getting HTTP 302 with your directory path in the location.
So I'm afraid you might be stuck unless.. your hosting lets you follow symbolic links; so you can link to that location (assuming you have shell access or this is possible using FTP or your control panel) under your current document root.
Edit: It actually mentions URL-file phase hook in the docs so now I suspect the directory directives aren't allowing enough permissions.
This tells you what you need to know.
The requested URL /www/htdocs/customername/manual/resourcename.htm
was not found on this server.
It interprets RewriteRule ^manual(/(.*))?$ /www/htdocs/customername/manual/$2 [L] to mean rewrite example.com/manual/ as if it were example.com/www/htdocs/customername/manual/.
Try
RewriteRule ^manual(/(.*))?$ /customername/manual/$2 [L]
instead.