开发者

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 somet开发者_运维百科hing 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.


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. :)


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 /


This might work:

RewriteRule ^myParentDir/[A-Z0-9_-]+$ %{REQUEST_URI}/ [NS,L,R=301]

However, I'm not sure why you think you need this at all. Just make your CSS / JS / image file rewrite rule look something like this:

RewriteRule ^galleries/([A-Za-z0-9_-]+/)*(css|js|images)/(.*)$ ./$2/$3

and everything should work just fine regardless of whether the browser requests /somedir/galleries/css/whatever.css or /somedir/galleries/cats/css/whatever.css or even /somedir/galleries/cats/persian/calico/css/whatever.css.

Ps. One problem with this rule is that it prevents you from having any galleries names "css", "js" or "images". You might want to fix that by naming those virtual directories something like ".css", ".js" and ".images", or using some other naming scheme that doesn't conflict with valid gallery names.


I'm not sure I complelty understand your problem.

The trailing slash redirection is done automatically on most Apache installation because of mod_dir module (99% of chance you'have the mod_dir module).

You may need to add:

DirectorySlash On

But it's the default value.

So. If you access foo/bar and bar is not a file in foo directory but a subdirectory then mod_dir performs the redirection to foo/bar/.

The only thing I known that could break this is the Option Multiviews which is maybe trying to fin a bar.php, bar.php, bar.a-mime-extension-knwon-by-apache in the directory. So you could try to add:

Option -Multiviews

And remove all rewriteRules. If you do not get this default Apache behavior you'll maybe have to look at mod-rewrite, but it's like using a nuclear bomb to kill a spider. Nuclear bombs may get quite touchy to use well.

EDIT: For the trailing slash problem with mod-rewrite you can check this documentation howto, stating this should work:

RewriteEngine  on
RewriteBase    /myParentDir/
RewriteCond    %{REQUEST_FILENAME}  -d
RewriteRule    ^(.+[^/])$           $1/  [R]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜