【问题标题】:How to do a mod_rewrite redirection to relative URL如何进行 mod_rewrite 重定向到相对 URL
【发布时间】:2011-12-07 16:49:12
【问题描述】:

我正在尝试实现漂亮 URL 的基本 URL 重定向,并且由于图像、CSS 等也位于同一路径中,我需要确保如果访问 URL 时没有尾部斜杠,则添加它自动。

如果我这样输入绝对 URL,这会很好:

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

但是,如果我将其更改为相对 URL,这样我就不必每次在文件夹中移动内容时都更改它,这根本行不通。

这些都是我尝试过的,但都不起作用,或者将我重定向到服务器的实际内部目录路径,例如 /public_html/...:

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

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

进行 URL 重定向的正确方法是什么,以便用户输入如下内容:

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

他被重定向到(通过 HTTP 301 或 302):

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

谢谢。

编辑:添加更多细节,因为它似乎并不清楚。 假设我正在实现一个画廊,并且我想使用 mod_rewrite 拥有漂亮的 URL。 所以,我想有如下网址:

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

显示猫的缩略图,而:

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

它显示了所有猫的缩略图中的一张图像,名为 persian。 所以实际上物理目录结构和重写如下:

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

所以我想做的是在 /somedir 中放置一个 .htaccess 文件,该文件捕获对 /galleries 的所有请求,并根据其后的虚拟子目录,将它们用作重写中的占位符,并使用 2 条重写规则:

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]

现在的问题是画廊脚本实际上需要一些 CSS、Javascript 和图像,分别位于 http://www.domain.com/somedir/csshttp://www.domain.com/somedir/jshttp://www.domain.com/somedir/images

我不想硬编码任何绝对 URL,因此 CSS、JS 和图像将使用相对 URL(./css、./js、./images 等)来引用。所以我可以按如下方式重写 URL:

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

问题是因为http://www.domain.com/somedir/galleries/cats是一个虚拟目录,所以上面的方法只有在用户输入时才有效:

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

如果用户省略了尾部斜杠 mod_dir 将不会添加它,因为实际上这个目录实际上并不存在。

如果我使用绝对 URL 进行重定向重写:

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

但我不想硬编码 URL 前缀,因为我希望能够将它放在我想要的任何子目录中的任何域中,所以我尝试了这个:

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

但它会重定向到:

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

这显然不是我想要的。

编辑:进一步说明

我正在寻找的解决方案是避免在 .htaccess 中硬编码域名或文件夹路径。我正在寻找一种解决方案,如果我将 .htaccess 与其余的脚本和资源打包在一起,无论用户在他的 Web 服务器上将其解压缩到何处,它都可以开箱即用。除了这个斜杠问题之外,所有的工作都是这样的。

因此,任何涉及以任何方式在 .htaccess 中硬编码父目录或网络服务器路径的解决方案都不是我想要的。

【问题讨论】:

  • @DoktorJ 我的帖子的编辑回答了你的问题吗?
  • 你应该选择你接受的答案,如果这里有任何帮助的话。

标签: apache mod-rewrite redirect


【解决方案1】:

这是直接来自Apache Documentation 的解决方案(在“斜线问题”下):

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

这里是 a solution,它测试 REQUEST_URI 的尾部斜杠,然后添加它:

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

这里是another solution,可让您免除某些 REQUEST_URI 模式:

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

希望这些帮助。 :)

【讨论】:

    【解决方案2】:

    此规则应在任何不是真实文件/目录的 URL 中添加尾部斜杠(我相信这是您所需要的,因为 Apache 通常会自动为现有目录执行重定向)。

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

    编辑:

    为了防止 Apache 附加相对于文档根目录的路径,您必须使用 RewriteBase。因此,例如,在应作为应用程序根目录的文件夹中,添加以下内容,它会覆盖物理路径:

    RewriteBase /
    

    【讨论】:

    • 似乎使用 RewriteBase 的诀窍是有一个前导 一个斜杠;例如,“/foo/”而不是“/foo”或“foo/”。 RewriteBase 对我来说仍然有点挑剔,但最终它成功了。谢谢!
    【解决方案3】:

    可能工作:

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

    但是,我不确定你为什么认为你需要这个。只需让你的 CSS / JS / 图像文件重写规则看起来像这样:

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

    无论浏览器请求/somedir/galleries/css/whatever.css/somedir/galleries/cats/css/whatever.css 还是/somedir/galleries/cats/persian/calico/css/whatever.css,一切都应该正常工作。

    附言。此规则的一个问题是它会阻止您使用任何画廊名称“css”、“js”或“images”。您可能希望通过将这些虚拟目录命名为“.css”、“.js”和“.images”之类的名称来解决此问题,或者使用与有效画廊名称不冲突的其他命名方案。

    【讨论】:

      【解决方案4】:

      我不确定我是否完全理解您的问题。

      由于 mod_dir 模块,尾部斜杠重定向在大多数 Apache 安装中自动完成(99% 的机会你有 mod_dir 模块)。

      您可能需要添加:

      DirectorySlash On
      

      但这是默认值。

      所以。如果您访问foo/bar 并且 bar 不是 foo 目录中的文件而是子目录,则 mod_dir 执行重定向到 foo/bar/

      我所知道的唯一可以打破这一点的是Option Multiviews,它可能试图在目录中找到 bar.php、bar.php、bar.a-mime-extension-knwon-by-apache。所以你可以尝试添加:

      Option -Multiviews
      

      并删除所有 rewriteRules。如果您没有获得这种默认的 Apache 行为,您可能需要查看 mod-rewrite,但这就像使用核弹杀死蜘蛛一样。核弹可能很难用好。

      编辑: 对于 mod-rewrite 的尾部斜杠问题,您可以查看 documentation howto,说明这应该可以:

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

      【讨论】:

      • 感谢您的回复。但是,请记住,这些不是实际的目录。这些实际上并不存在,只是漂亮 URL 的虚拟目录。所以实际上 URL:mydomain.com/somedir/myVirtualParentDir 不存在。没有它,我将获得图像等的相关链接无效。
      • 为什么要包含 RewriteBase?这是我要避免的全部要点。我不想在我的 .htaccess 中硬编码路径。我想要在我放置的任何子目录中都可以使用的东西。这与在重定向中将完整路径指定为 mydomain.com/myParentDir 没有什么不同,这是我不想要的。其余的与我原来的问题完全相同,其中 $1/ 重定向到实际的物理 URL 而不是虚拟的。您的建议只会重定向到物理 myParentDir/theRest 而不是 /myVirtualDir/theRest。
      • @jbx:阅读链接,这必须放在顶级目录中,适用于所有子目录。
      • 谢谢,事实上,在我发布这个问题之前,我也确实读过。抱歉,如果我似乎无法解决问题,但我不想在父目录的 .htaccess 中硬编码 RewriteBase,它会破坏我想要实现的整个范围。如果它涉及任何硬编码或提及父目录的名称,则相当于硬编码本地 .htaccess 中的完整路径。我需要把它打包好,以便用户可以将它解压缩到他想要在他的网络服务器上的任何文件夹中,并且可以在不摆弄重写规则的情况下工作。
      猜你喜欢
      • 1970-01-01
      • 2010-11-09
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2016-12-12
      • 2012-11-12
      相关资源
      最近更新 更多