【问题标题】:Combine two Mod Rewrite Rules结合两个 Mod 重写规则
【发布时间】:2011-07-19 22:09:51
【问题描述】:

当前状态: 首先,我想指出这个问题与我两天前发布的一个问题非常相关。从那以后,我试图以不同的方式解决我面临的问题,并且遇到了不同的问题。我希望这不构成任何形式的“双重发布”?

我创建了两个似乎独立工作以创建所需效果的 mod 重写规则。如下所示:

RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*/)?([A-Za-z0-9.-]+)_([A-Za-z0-9.-]*) $1?$2=$3&%1 [L]

上述规则采用这样的 URL:

www.site.com/param1/thing/sortorder_5/getparam2_6/

并将其转换为:

www.site.com/param1/thing/?sortorder=5&getparam2_6/

第二条规则如下:

RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(.+)) $1?$2=$3&%1 [L]

这需要一个这样的 URL:

http://www.site.com/cmd/param1/thing/cmd2/param2/

并将其转换为:

http://www.site.com?cmd=param1/thing&cmd2=param/

期望的结果:

我想合并这两个重写规则,以便我可以执行以下操作:

http://www.site.com/cmd/param1/cmd2/param2/sortorder_5

转换为:

http://www.site.com?cmd=param1&cmd2=param2&sortorder=5

任何告诉我如何开始这样做的人都会非常友善。几天来,我已经尝试了很多 mod 重写代码,但没有运气。我的 regex/mod 重写知识真的没有达到标准,所以对此我深表歉意!整个 mod 重写代码粘贴在下面。谢谢。

RewriteEngine On

# This block works fine in isolation
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*/)?([A-Za-z0-9.-]+)_([A-Za-z0-9.-]*) $1?$2=$3&%1 [L]

# This block also works fine in isolation
RewriteCond %{QUERY_STRING} (.*)
RewriteRule ^(.*/)?((?:cmd)[^/]*)/((?!(?:cmd)[.+]*)(.+)) $1?$2=$3&%1 [L]

# This block should append the query string to index.php (front controller)
RewriteCond %{QUERY_STRING} ^(.*)$
RewriteRule ^.*$ index.php?%1 [L]

【问题讨论】:

  • 如果您可以控制index.php,我建议您只需执行RewriteRule ^(.*)$ ?query=$1 [L,QSA] 之类的操作并在脚本中解析查询。这样,除了使请求的解析更容易之外,您不依赖于 mod_rewrite 规则(可以很容易地与其他服务器一起使用)。
  • 顺便说一句,你为什么要这样使用RewriteCond %{QUERY_STRING} (.*)?我建议只在重写规则上使用QSA 标志。

标签: regex apache .htaccess mod-rewrite rewrite


【解决方案1】:

这是经过测试并且有效的:

RewriteEngine On
RewriteRule ^(cmd[^/]*)/([^/]+)/?(.*)$ $3?$1=$2 [QSA,NC,L]
RewriteRule ^([a-z\d.-]+)_([a-z\d.-]+)/?(.*)$ $3?$1=$2 [QSA,NC,L]

请参阅mod_rewrite docs 了解这些标志。

示例请求:

http://localhost:8080/test/cmd1/foo/cmd2/bar/foo_bar/cmd42/everything

结束于:

http://localhost:8080/test/index.pl?cmd42=everything&foo=bar&cmd2=bar&cmd1=foo

.htaccess 位于/test/index.pl 打印其查询字符串:

cmd42=everything&foo=bar&cmd2=bar&cmd1=foo

这个请求有重定向日志:

[rid#2f0b590/initial] (2) [perdir /root_http/test/] rewrite 'cmd1/foo/cmd2/bar/foo_bar/cmd42/everything' -> 'cmd2/bar/foo_bar/cmd42/everything?cmd1=foo'
[rid#2f0b590/initial] (2) [perdir /root_http/test/] strip document_root prefix: /root_http/test/cmd2/bar/foo_bar/cmd42/everything -> /test/cmd2/bar/foo_bar/cmd42/everything
[rid#2f0b590/initial] (1) [perdir /root_http/test/] internal redirect with /test/cmd2/bar/foo_bar/cmd42/everything [INTERNAL REDIRECT]
[rid#10dec40/initial/redir#1] (2) [perdir /root_http/test/] rewrite 'cmd2/bar/foo_bar/cmd42/everything' -> 'foo_bar/cmd42/everything?cmd2=bar'
[rid#10dec40/initial/redir#1] (2) [perdir /root_http/test/] strip document_root prefix: /root_http/test/foo_bar/cmd42/everything -> /test/foo_bar/cmd42/everything
[rid#10dec40/initial/redir#1] (1) [perdir /root_http/test/] internal redirect with /test/foo_bar/cmd42/everything [INTERNAL REDIRECT]
[rid#2e16d90/initial/redir#2] (2) [perdir /root_http/test/] rewrite 'foo_bar/cmd42/everything' -> 'cmd42/everything?foo=bar'
[rid#2e16d90/initial/redir#2] (2) [perdir /root_http/test/] strip document_root prefix: /root_http/test/cmd42/everything -> /test/cmd42/everything
[rid#2e16d90/initial/redir#2] (1) [perdir /root_http/test/] internal redirect with /test/cmd42/everything [INTERNAL REDIRECT]
[rid#2f0d558/initial/redir#3] (2) [perdir /root_http/test/] rewrite 'cmd42/everything' -> '?cmd42=everything'
[rid#2f0d558/initial/redir#3] (2) [perdir /root_http/test/] strip document_root prefix: /root_http/test/ -> /test/
[rid#2f0d558/initial/redir#3] (1) [perdir /root_http/test/] internal redirect with /test/ [INTERNAL REDIRECT]
[rid#2f0eac8/initial/redir#4] (1) [perdir /root_http/test/] pass through /root_http/test/
[rid#10c98b0/subreq] (1) [perdir /root_http/test/] pass through /root_http/test/index.html
[rid#10c98b0/subreq] (1) [perdir /root_http/test/] pass through /root_http/test/index.shtml
[rid#10c98b0/subreq] (1) [perdir /root_http/test/] pass through /root_http/test/index.cgi
[rid#10c98b0/subreq] (1) [perdir /root_http/test/] pass through /root_http/test/index.fcgi
[rid#10c98b0/subreq] (1) [perdir /root_http/test/] pass through /root_http/test/index.pl

可以通过在服务器配置中添加此日志来查看此日志:

RewriteLog "logs/rewrite.log"
RewriteLogLevel 2

【讨论】:

  • 很遗憾,没有得到答案,但非常感谢您的回复。我确实喜欢您将整个 URL 附加到 index.php 并以这种方式解析的建议;更直接。不过,我很好奇,这如何允许它在更多服务器上使用?是否必须在服务器配置中启用 mod 重写才能使单个 RewriteRule 生效?
  • 其他服务器可能有其他方法将此类数据传递给您的脚本。您可以在配置或其他类型的重写规则中设置。
  • 效果很好!恐怕我还有另一个问题 - 我忘了在我的描述中包含一个非常重要的点:cmd 值可以跨越多个目录。因此 cmd/valuepart1/valuepart2/ 将是 URL 中的一个命令,可能如下所示:www.site.com/cmd/valpart1/valpart2/cmd2/anotherval/regulargetparam_here。我尝试在您的正则表达式的修改版本中使用负前瞻,但没有成功。你有机会如何实现这一目标吗?如果你抽不出时间回复,当然,我还是把上面的标记为答案!你帮了大忙。谢谢!
  • cmd/valpart1/valpart2 的结果查询字符串应该是什么?价值观应该在哪里结束? cmd/val_part1/val_part2呢?
  • @Qtax.Sorry,我只能在评论中放这么多。它应该解析为cmd=valpart1/valpart2&cmd2=anotherval&regulargetparam=here。希望能解决这个问题。
猜你喜欢
  • 2010-11-13
  • 2012-05-13
  • 2012-09-27
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多