多个htacces mod_rewrites在一个文件中

时间:2017-08-17 00:02:36

标签: php apache .htaccess mod-rewrite

我的应用程序有两个重写规则:

第一条规则是/chef/index.php的规则:

/chef/name -> /chef/?id=1234

第二条规则是/recipes/index.php的规则:

/r/name/nice-name-for-recipe ->
    /recipes/?id=1234&nice_name=nice-name-for-recipe-name

这两个规则分开工作,但如果我启用了这两个规则:

  • 第一个厨师规则不起作用,
  • 第二个食谱规则似乎有效。

我试图交换规则的顺序,但我仍然不能使它们都有效。

规则:

RewriteEngine On

RewriteRule ^([a-zA-Z0-9_-]+)/chef/$ $1 [QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /chef/index.php?id=$1 [QSA]

RewriteRule ^([a-zA-Z0-9_-]+)/r/$ $1/$2 [QSA]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /recipes/index.php?id=$1&nice_name=$2 [QSA]

2 个答案:

答案 0 :(得分:1)

在第一条规则中,您尝试匹配^([a-zA-Z0-9_-]+)/chef/$/chef/$表示它与以/chef/结尾的网址匹配, 因为$表示字符串的结尾,例如:

http://anything.dev/chef/

因此它与/chef/name/不匹配,它与/chef/匹配。

同样,您的第二条规则与/r/name/nice-name-for-recipe不匹配, 它匹配/r/$

这些规则只是告诉apache回退到静态文件。 如果您需要提供静态文件,这很有用 但他们与这个问题无关。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f

所以你的规则大致只是:

RewriteRule ^(.*)$ /chef/index.php?id=$1 [QSA]
RewriteRule ^(.*)$ /recipes/index.php?id=$1&nice_name=$2 [QSA]

现在很清楚,为什么这些规则分开工作,但只有第二个规则才能合并。

它们都匹配^(.*)$,即每个网址(静态文件的网址除外)。 因此,当把它们放在一起时,只有第二个获胜。

所以真正的规则效果是:

/chef/name ->
    /chef/index.php?id=/chef/name&nice_name=

/r/name/nice-name-for-recipe ->
    /chef/index.php?id=/r/name/nice-name-for-recipe&nice_name=

P.S。我认为这个问题的深层原因是:

  1. 您尝试编写正则表达式而不理解它们。

  2. 正则表达式语法很难理解。具体来说,$都用作模式和变量前缀。

  3. index.php代码很脏。它不应该盲目地接受网址。如果index.php出错,则这两条规则似乎不起作用。脏代码很难检测和定位问题,而且不安全(攻击者可以构建危险的特殊网址)。

  4. 由于RewriteRule ^(.*)$ /recipes/index.php?id=$1&nice_name=$2 [QSA]未设置,您的IDE不足以警告您$2

答案 1 :(得分:0)

您写的是要将dev.website.com/chef/name转换为dev.website.com/chef/?id=1234。这不起作用,因为目标网址中的ID在源网址中不存在,因此您需要考虑如何在原始网址中包含该ID。

一旦您对其进行排序,我建议您阅读有关正则表达式的更多内容以修复mod_rewrite规则。 这是测试和解释正则表达式的绝佳资源:https://regex101.com/