Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do a mod_rewrite redirection to relative URL

I am trying to achieve a basic URL redirection for pretty-URLs, and due to images, CSS etc. also residing in the same path I need to make sure that if the URL is accessed without a trailing slash, it is added automatically.

This works fine if I put the absolute URL like this:

RewriteRule ^myParentDir/([A-Z0-9_-]+)$ http://www.mydomain.com/myParentDir/$1/ [R,nc,L]

But if I change this to a relative URL, so that I don't have to change it each time I move things in folders, this simply doesn't work.

These are what I tried and all do not work, or redirect me to the actual internal directory path of the server like /public_html/... :

RewriteRule ^myParentDir/([A-Z0-9_-]+)$ ./myParentDir/$1/ [R,nc,L]

RewriteRule ^myParentDir/([A-Z0-9_-]+)$ myParentDir/$1/ [R,nc,L]

What is the right way to do a URL redirection so that if the user enters something like:

http://www.mydomain.com/somedir/myVirtualParentDir/myVirtualSubdir

he gets redirected to (via HTTP 301 or 302):

http://www.mydomain.com/somedir/myVirtualParentDir/myVirtualSubdir/

Thanks.

EDIT: Adding some more details because it does not seem to be clear. Lets say I am implementing a gallery, and I want to have pretty URLs using mod_rewrite. So, I would like to have URLs as follows:

http://www.mydomain.com/somedir/galleries/cats

which shows thumbnails of cats, while:

http://www.mydomain.com/somedir/galleries/cats/persian

which shows one image from the thumbnails of all cats, named persian. So in actual fact the physical directory structure and rewriting would be as follows:

http://www.domain.com/somedir/gallery.php?category=cats&image=persian

So what I want to do is put a .htaccess file in /somedir which catches all requests made to /galleries and depending on the virtual subdirectories following it, use them as placeholders in the rewriting, with 2 rewrite rules:

RewriteRule ^galleries/(A-Z0-9_-]+)/$ ./gallery.php?category=$1 [nc]
RewriteRule ^galleries/(A-Z0-9_-]+)/+([A-Z0-9_-]+)$  ./gallery.php?category=$1&image=$2 [nc]

Now the problem is that the gallery script in fact needs some CSS, Javascript and Images, located at http://www.domain.com/somedir/css, http://www.domain.com/somedir/js, and http://www.domain.com/somedir/images respectively.

I don't want to hardcode any absolute URLs, so the CSS, JS and Images will be referred to using relative URLs, (./css, ./js, ./images etc.). So I can do rewriting URLs as follows:

RewriteRule ^galleries/[A-Z0-9_-]+/css/(.*)$ ./css/$1 [nc]

The problem is that since http://www.domain.com/somedir/galleries/cats is a virtual directory, the above only works if the user types:

http://www.domain.com/somedir/gallaries/cats/

If the user omits the trailing slash mod_dir will not add it because in actual fact this directory does not actually exist.

If I put a redirect rewrite with the absolute URL it works:

RewriteRule ^galleries/([A-Z0-9_-]+)$ http://www.mydomain.com/subdir/galleries/$1/ [R,nc,L]

But I don't want to have the URL prefix hardcoded because I want to be able to put this on whatever domain I want in whatever subdir I want, so I tried this:

RewriteRule ^galleries/([A-Z0-9_-]+)$ galleries/$1/ [R,nc,L]

But instead it redirects to:

http://www.mydomain.com/home/myaccount/public_html/subdir/galleries/theRest

which obviously is not what I want.

EDIT: Further clarifications

The solution I am looking for is to avoid hardcoding the domain name or folder paths in .htaccess. I am looking for a solution where if I package the .htaccess with the rest of the scripts and resources, wherever the user unzips it on his web server it works out of the box. All works like that apart from this trailing slash issue.

So any solution which involves hardcoding the parent directory or the webserver's path in .htaccess in any way is not what I am looking for.

like image 722
jbx Avatar asked Oct 14 '11 11:10

jbx


People also ask

What does IfModule mod_rewrite C mean?

The <IfModule mod_rewrite. c>... </IfModule> block ensures that everything contained within that block is taken only into account if the mod_rewrite module is loaded. Otherwise you will either face a server error or all requests for URL rewriting will be ignored.


2 Answers

This rule should add a trailing slash to any URL which is not a real file/directory (which is, I believe, what you need since Apache usually does the redirect automatically for existing directories).

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+[^/])$ $1/ [L,R=301]

Edit:

In order to prevent Apache from appending the path relative to the document root, you have to use RewriteBase. So, for instance, in the folder meant to be your application's root, you add the following, which overrides the physical path:

RewriteBase /
like image 30
Kevin Stricker Avatar answered Oct 26 '22 00:10

Kevin Stricker


Here's a solution straight from the Apache Documentation (under "Trailing Slash Problem"):

RewriteCond    %{REQUEST_FILENAME}  -d
RewriteRule    ^(.+[^/])$           $1/  [R]

Here's a solution that tests the REQUEST_URI for a trailing slash, then adds it:

RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.+) http://www.example.com/$1/ [R=301,L]

Here's another solution that allows you to exempt certain REQUEST_URI patterns:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !example.php
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://domain.com/$1/ [L,R=301]

Hope these help. :)

like image 96
whoisgregg Avatar answered Oct 25 '22 22:10

whoisgregg