.htaccess rewrite root to folder, yet block direct urls to same folder - apache

I've been researching and trying for a week to accomplish this, but I haven't been able to find my solution. I'm sure it's possible, but I'm just not an expert in the depths of voodoo magic.
The setup:
An installation of MantisBT located in
mysite.com/mantisbt/currentver/mantis-1.3.19
When I perform an upgrade, I want to archive all old versions and old
database dumps to /mantisbt/oldversions/ to keep things tidy.
I also have other utilities and pages in various subdirectories, for
instance "mysite.com/utils"
The goal:
I want users to type in mysite.com/ (root) and have the URL rewritten
(transparently) to /mantisbt/currentver/mantis-1.3.19/ so that they
don't see my directory structure and it looks like the mantisbt app is
located in the root directory.
I also want protection from anyone trying to directly access a
subdirectory beginning with "/mantis". For instance, if
someone directly types mysite.com/mantisbt/currentver/mantis-1.3.19/
into their browser, I want them redirected back to the root directory
so they access the site from root just like everyone else.
I also need to allow my other subdirectories like mysite.com/utils to
be accessible if I type in the full path to them.
The biggest problem I've encountered is that Apache loops through your .htaccess file again every time the URL changes. So I get stuck in these rewrite loops. I've tried looking at every possible tool that Apache offers, but I'm seriously outgunned here. I could provide examples of what I've tried, they're obviously not correct, but ask me and I can post them.

You'd be far better off altering the DocumentRoot in your httpd.conf, and mapping in the utils directory, via a Location directive. It will be far cleaner, and Apache won't have to do some trickery with every request.
Anyway something along the following lines should work.
# Stop direct access
RewriteCond %{HTTP_REFERER} !mysite.com [NC]
RewriteRule /?mantisbt/currentver/mantis-1.3.19 / [NC,L,R=301]
# Internally Rewrite everything apart from /utils to /mantisbt/mantis-1.3.19/
RewriteCond %{HTTP_REFERER} !mysite.com [NC]
RewriteCond %{REQUEST_URI} !/utils [NC]
RewriteRule .* /mantisbt/currentver/mantis-1.3.19%{REQUEST_URI} [L]

Related

Apache 301 redirect with get parameters

I am trying to do a 301 redirect with lightspeed webserver htaccess with no luck.
I need to do a url to url redirect without any related parameters.
for example:
from: http://www.example.com/?cat=123
to: http://www.example.com/some_url
I have tried:
RewriteRule http://www.example.com/?cat=123 http://www.example.com/some_url/ [R=301,L,NC]
Any help will be appreciated.
Thanks for adding your code to your question. Once more we see how important that is:
your issue is that a RewriteRule does not operate on URLs, but on paths. So you need something like that instead:
RewriteEngine on
RewriteRule ^/?$ /some_url/ [R=301,L,NC,QSD]
From your question it is not clear if you want to ignore any GET parameters or if you only want to redirect if certain parameters are set. So here is a variant that will only get applied if some parameter is actually set in the request:
RewriteEngine on
RewriteCond %{QUERY_STRING} (?:^|&)cat=123(?:&|$)
RewriteRule ^/?$ /some_url/ [R=301,L,NC,QSD]
Another thing that does not really get clear is if you want all URLs below http://www.example.com/ (so below the path /) to be rewritten, or only that exact URL. If you want to keep any potential further path component of a request and still rewrite (for example http://www.example.com/foo => http://www.example.com/some_url/foo), then you need to add a capture in your regular expression and reuse the captured path components:
RewriteEngine on
RewriteRule ^/?(.*)$ /some_url/$1 [R=301,L,NC,QSD]
For either of this to work you need to have the interpretation of .htaccess style files enabled by means of the AllowOverride command. See the official documentation of the rewriting module for details. And you have to take care that that -htaccess style file is actually readable by the http server process and that it is located right inside the http hosts DOCUMENT_ROOT folder in the local file system.
And a general hint: you should always prefer to place such rules inside the http servers host configuration instead of using .htaccess style files. Those files are notoriously error prone, hard to debug and they really slow down the server. They are only provided as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

htaccess RewriteRule problems

I have a web page which works fine on live server. However some links to files (jpg, pdf and others) which are created with cms editor contain relative paths.
When I run that page on my local test server which serves the pages out of a sub folder of localhost the relative paths to the files are wrong since they are missing the subfolder at the beginning. The html page loads fine. It's just some files in it that have wrong path and won't load.
page loads from http://localhost/level1/
files are trying to load from http://localhost/level2/ and I get 404s.
They should be loading from http://localhost/level1/level2/
So I setup a RewriteRule to correct the path but no matter what I have tried I can't get it to work. I have tried various flags including [R,L] but nothing changes the URI in the html.
currently I have:
RewriteRule ^/level2/(.*)$ /level1/level2/$1 [R]
Any suggestions?
Thanks
Sounds like those links are not relative paths but absolute ones (starting with a leading slash (/). That is why the issue occurs at all. Relative paths make much more sense.
This would be the version to be used inside your http servers host configuration:
RewriteEngine on
RewriteRule ^/level2/(.*)$ /level1/level2/$1 [L,QSA]
Here the version for .htaccess style files (note the missing leading slash):
RewriteEngine on
RewriteRule ^level2/(.*)$ /level1/level2/$1 [L,QSA]
You could use a version that can be used in both situations:
RewriteEngine on
RewriteRule ^/?level2/(.*)$ /level1/level2/$1 [L,QSA]
Note however that in general one should always prefer to place such rules inside the http servers host configurations. .htaccess style files are notoriously error prone, hard to debug and they really slow down the server, often for nothing. .htaccess style files only offer a last option for those who are using a really cheap web hosting provider. Or for situations where a web application has to write its own rewrite rules, which obviously is a security nightmare on its own...

Apache - mod_rewrite how to prefer files instead of directories (if both have same name)?

I have very similar problem like this one: Apache mod_rewrite - prefer files over directories with pretty URLs
However it is not same, and solutions mentioned in above link doesn't work for me.
My directory structure looks like this:
/pages/articles/january.php
/pages/articles.php
/pages/home.php
/articles/
/index.php
Now, I am including in index.php pages (depending on url).
For example, when user types address www.domain.com (or www.domain.com/home), index.php will include /pages/home.php
But if I enter this URL: www.domain.com/articles it will make link something like this: www.domain.com/articles/?page[]=articles (in other words index.php won't include /pages/articles.php file)
On the other hand, this works perfectly: www.domain.com/articles/january
This is my htaccess file:
RewriteEngine On
RewriteBase /
RewriteRule ^([a-zA-Z0-9+]*)/([a-zA-Z0-9+]*)$ %{DOCUMENT_ROOT}/index.php?page[]=$1&page[]=$2 [QSA,L]
RewriteRule ^([a-zA-Z0-9+]*)$ %{DOCUMENT_ROOT}/index.php?page[]=$1 [QSA,L]
I use array for page because I can have subpages (and subpages work fine!).
EDIT: I have found this however it doesn't solves my problem :(
Can someone tell me why it does this and how to fix it?
Or, how can I give priority to files instead directories?
EDIT 2: I solved it by removing "/articles/" directory, however I am still interested how to make it work through htaccess file rules.
Per the comments above, your original issue was worked around by removing the articles directory, but you still wanted to be able to deal with directories in that sort of situation.
You'd probably want to split into two sets of rules. Have an earlier rule that uses the -d flag in a RewriteCond to catch directories so that it could treat them differently as needed. Alternately, ignore directories in the first rule by negating the flag (!-d) then catch them in the later rule.

How manage several folders in my domain?

I want create subdomains like this:
domain.com/type/city
An examples:
domain.com/restaurants/new_york
domain.com/hotels/new_york
domain.com/restaurants/chicago
I have thousand of cities in a mysql database.
I thinked in some options:
Thousand of folders with an index.php for redirect (I think wrong way).
Create an sitemap with all links (domain.com?type=hotels&city=chicago) and manage they by code with the database.
Apache?
Please, which will be the best way for this? Thanks in advance!
You can solve this with a combination of PHP and Apache configuration. That is the most common solution and seen in popular PHP website software such as Drupal and Wordpress.
The idea is to let Apache send all traffic to one index.php file and pass the rest of the path as a parameter for PHP to handle with it.
You will need to be carefull with a few edgecases though; if file such as ./public/styles.css is requested, you don't want to serve that trough your PHP application but want apache to serve the file directly. Existing files will need to be handled by apache, all else by you application.
In your .htaccess:
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
The first line tells Apache to send normal files by itlself. Second line does the same for existing directories. Third line avoids that browsers (most notably version IE6) who request the example.com/favicon.ico don't hammer your PHP application.
Then it passes everything along to index.php and adds the rest of the path into the q param.
Inside index.php you can then read that, and take action with that:
<?php
$path = $_GET['q'];
$params = explode('/', $path);
print $path;
print_r($params);
?>
Thousands of folders would be the wrong way that is for sure.
If you start creating the sitemap with links of the type domain.com/?type=hotels&city=chicago you get a nice structure that you can manage programatically.
First get this started and working, then look up .htaccess and mod_rewrite which you can then use to map from domain.com/type/city to your links already functioning.
This seems both to be a good strategy for getting something working fast, and for ending up with the prettiest solution.

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.