【问题标题】:Applying multiple rules with .htaccess使用 .htaccess 应用多个规则
【发布时间】:2019-12-21 09:44:22
【问题描述】:

我现在的.htaccess长这样,目前有保证https-access的功能:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

但是,我希望它做得更多,因为我当前的链接结构对 SEO 并不友好。基本上,我想进行更改,以便我可以输入左侧的 URL,并加载右侧的 URL。

https://nexuscompendium/heroes/li-li/ --> https://nexuscompendium.com/hero.php?h=li-li
https://nexuscompendium/heroes/       --> https://nexuscompendium.com/heroes/

我想出了以下似乎工作得很好...只要上面的 HTTPS 规则也不是活动的,因为其他规则只是再次删除了“https://”。

    RewriteRule heroes\/role\/([a-zA-Z]+)(\/?)$       herorole.php?r=$1     [L]
    RewriteRule heroes\/([a-zA-Z\-]+)(\/?)$           hero.php?h=$1         [L]
    RewriteRule battlegrounds\/([a-zA-Z\-]+)(\/?)$    battleground.php?b=$1 [L]
    RewriteRule rotations\/([0-9\-]+)(\/?)$           rotation.php?r=$1     [L]
    RewriteRule sales\/([0-9\-]+)(\/?)$               sale.php?s=$1         [L]
    RewriteRule predictions\/([0-9\-]+)(\/?)$         predictions.php?w=$1  [L]
    RewriteRule universes\/([a-zA-Z\-]+)(\/?)$        universe.php?u=$1     [L]
    RewriteRule subuniverses\/([a-zA-Z\-]+)(\/?)$     subuniverse.php?s=$1  [L]
    RewriteRule events\/seasonal\/([a-zA-Z\-]+)(\/?)$ seasonal.php?s=$1     [L]
    RewriteRule events\/([a-zA-Z0-9\-]+)(\/?)$        event.php?e=$1        [L]
    RewriteRule skins\/([a-zA-Z0-9\-]+)(\/?)$         skin.php?s=$1         [L]
    RewriteRule mounts\/([a-zA-Z0-9\-]+)(\/?)$        mount.php?m=$1        [L]
    RewriteRule ([a-zA-Z]+)(\/?)$                     $1.php

长话短说:我可以结合上述规则吗?如果可以,如何结合?如果没有,有没有办法确保 HTTPS 重定向?

提前谢谢❤

编辑:感谢 .htaccess 循环直到没有更多规则可以完成(以及在最后一个 RewriteRule 中略微添加 ^ 的知识,我得到了它的工作,如下所示:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

<IfModule mod_rewrite.c>
    RewriteRule ^heroes\/role\/([a-zA-Z]+)(\/?)$       herorole.php?r=$1     [L]
    RewriteRule ^heroes\/([a-zA-Z\-]+)(\/?)$           hero.php?h=$1         [L]
    RewriteRule ^battlegrounds\/([a-zA-Z\-]+)(\/?)$    battleground.php?b=$1 [L]
    RewriteRule ^rotations\/([0-9\-]+)(\/?)$           rotation.php?r=$1     [L]
    RewriteRule ^sales\/([0-9\-]+)(\/?)$               sale.php?s=$1         [L]
    RewriteRule ^predictions\/([0-9\-]+)(\/?)$         predictions.php?w=$1  [L]
    RewriteRule ^subuniverses\/([a-zA-Z\-]+)(\/?)$     subuniverse.php?s=$1  [L]
    RewriteRule ^universes\/([a-zA-Z\-]+)(\/?)$        universe.php?u=$1     [L]
    RewriteRule ^events\/seasonal\/([a-zA-Z\-]+)(\/?)$ seasonal.php?s=$1     [L]
    RewriteRule ^events\/([a-zA-Z0-9\-]+)(\/?)$        event.php?e=$1        [L]
    RewriteRule ^skins\/([a-zA-Z0-9\-]+)(\/?)$         skin.php?s=$1         [L]
    RewriteRule ^mounts\/([a-zA-Z0-9\-]+)(\/?)$        mount.php?m=$1        [L]
    RewriteRule ^([a-zA-Z]+)(\/?)$                    $1.php                
</IfModule>

【问题讨论】:

  • 据我所知,这并不是一个关于重写规则的问题。上面的规则确实not 将客户端从 https 重定向到 http 协议(这实际上是不可能自动实现的)。这里有两个可能的问题:1.您需要注意将重定向到 https 高于该动态配置文件(“.htaccess”)中的其他规则,否则请求不会被重定向到 https . 2.你有一些应用程序逻辑再次重定向到http(这也会导致浏览器警告和问题)。
  • 您应该能够在查看浏览器开发控制台时进行调试,检查其中的“网络”选项卡。这是您将看到发送的实际重定向的地方。
  • 我尝试先添加 HTTPS 部分,它可以工作(也由我用来测试的工具确认:htaccess.madewithlove.be)。但是,我不知道是什么原因导致它再次“重定向”到 http?
  • 那么,当您按照建议进行调试时,您会看到哪些重定向?您如何确保您没有查看缓存的结果?此外,了解当您被“返回”到 http 时实际发生的情况也会很有趣。仅仅因为今天的浏览器都不会遵循这样的重定向......
  • 我知道的唯一调试是我提供的链接。我是一个菜鸟,所以我为什么要问,毕竟。因为 [R=301] 是可以理解的,所以首先使用 https 规则会使所有后续无效 - 如果我删除它,并且满足列出的规则之一,它满足条件 - 但恢复为 http,完全无视 https 规则。我可以使用哪些其他工具,而不会在服务器上删除潜在的错误 .htaccess?否则,我必须检查浏览器内的方式,但我希望有更好的方式。

标签: .htaccess mod-rewrite


【解决方案1】:

我选择在这里提供另一个答案。不是因为您的错误,您自己找到了一个可行的设置真是太好了!

但是,您的实现可以进行相当多的优化。是的,您实现的内容是完全可能的,但是应用的规则越多,http 服务器的速度就越慢(我们在这里讨论的是正则表达式匹配,即 相当 一个昂贵的操作)。所以可能值得稍微浓缩一下:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301]

    RewriteRule ^/?heroes/role/([a-zA-Z]+)(/?)$       /herorole.php?r=$1 [END]
    RewriteRule ^/?events/seasonal/([a-zA-Z-]+)(/?)$ /seasonal.php?s=$1 [END]

    RewriteCond %{REQUEST_URI} ^/?(\w+)s/([\w-]+)(/?)$
    RewriteCond /%1.php -f
    RewriteRule ^ /%1.php?h=%2 [END]

    RewriteRule ^/?([a-zA-Z]+)(/?)$                    /$1.php                
</IfModule>

这里有一些优化:

  1. 不需要重定向到 https 的模式,因为无论如何您都不会使用它捕获的内容。所以使用最简单的模式:^ 总是匹配的,因为每个字符串都有一个开头。
  2. 在重写规则中的模式开头使用^/? 使其可以在动态配置文件(“.htaccess”)中在真正的http 服务器配置中工作。更多关于这进一步。
  3. 大多数转义字符 (\) 不是必需的。将它们放在一边会使模式更易于阅读。
  4. 尽可能重定向到绝对路径,这有助于防止混淆。
  5. 在大多数情况下使用[END] 而不是[L] 如果你的http服务器不是太旧 ...如果该规则得到,它将终止整个重写过程已应用,而较旧的[L] 标志仅终止重写过程的此运行,因此该过程再次循环。这浪费了相当长的时间,因为在这种情况下肯定不会应用其他规则。因此,您为每个请求保存一次运行。
  6. 您可以将一些规则组合成更通用的规则,从而再次减少规则的数量。随着时间的推移,越来越多的规则汇集在一起​​,尤其如此……
  7. 真的需要不区分大小写 ([a-zA-Z]) 吗?您知道您分发的参考资料,您可以控制它们。没有人用手打字,对吧?此外,您通常可以使用\w 而不是[a-z],虽然不完全相同,但更简单。如前所述:经常,但它使事情更容易再次阅读。
  8. 还要确定您是否真的需要&lt;IfModule mod_rewrite.c&gt;。当重写模块没有安装时,它可以防止内部错误,当然。但是为了什么?通常应用程序将无法正常工作...

好的,这里当然可以说更多。但这可能已经足够了,现在给你一个起点。所以我将以一些一般性评论结束:


最好先从 302 临时重定向开始,稍后再将其更改为 301 永久重定向,前提是您确定一切都已正确设置。这样可以防止在尝试时出现缓存问题...

如果您使用上述规则收到内部服务器错误(http 状态 500),那么您很可能操作的是非常旧版本的 apache http 服务器。在这种情况下,您将在 http 服务器错误日志文件中看到不支持的 [END] 标志的明确提示。您可以尝试升级或使用旧的[L] 标志,在这种情况下它可能会起作用,尽管这取决于您的设置。

此实现同样适用于 http 服务器主机配置或动态配置文件(“.htaccess”文件)。显然重写模块需要在http服务器内部加载并在http主机中启用。如果您使用动态配置文件,您需要注意它的解释在主机配置中完全启用,并且它位于主机的 DOCUMENT_ROOT 文件夹中。

一般来说:您应该始终喜欢将此类规则放在 http 服务器主机配置中,而不是使用动态配置文件(“.htaccess”)。这些动态配置文件增加了复杂性,通常是导致意外行为的原因,难以调试,而且它们确实减慢了 http 服务器的速度。它们仅在您无法访问真正的 http 服务器主机配置(阅读:非常便宜的服务提供商)或坚持编写自己的规则的应用程序(这是一个明显的安全噩梦)的情况下作为最后一个选项提供。

【讨论】:

  • 很好,那里有很多很棒的优化指针——而且这些总是很棒!很高兴能扩展我的知识。只是一点点:我似乎无法发现(预测|旋转|销售)的日期部分会在精简版中被捕获? 0-9 是不是在某个地方漏掉了,还是我看错了?
  • 因为无论如何您只处理这些 URI 的第二部分,我认为您并不真正关心重写的级别,即基于字符的参数的数字。这就是我使用\w+ 而不是精确匹配模式的原因。我可以看到使用单独匹配模式的唯一原因是,如果您希望一个数字参数但获得一个基于字符的参数,那么您确实 想要重写,为什么会这样,但要依赖最后一个后备规则。如果是这种情况,那么请按照您的规定将规则分开,当然。
  • 啊,对不起,现在我明白你的意思了。正如我在上一条评论中所说的那样,我确实没有使用\w,我忘了替换它。修复它。对不起!
  • 是的,没错。我的目标是只捕获不同类型的预期/可能值,并最终将它们全部写出来,因为参数字母 (.php?X=) 通常不同,这(可悲)使规则更难概括,我我假设。
  • 当然,如果是这种情况并且您无法改变导致复杂性增加的原因,那么请遵守您的规则。
【解决方案2】:

感谢来自 arkascha 的知识,即 .htaccess 循环直到无法完成更多规则(以及在最后一个 RewriteRule 中略微添加 ^),我得到了它的工作,如下所示:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

<IfModule mod_rewrite.c>
    RewriteRule ^heroes\/role\/([a-zA-Z]+)(\/?)$       herorole.php?r=$1     [L]
    RewriteRule ^heroes\/([a-zA-Z\-]+)(\/?)$           hero.php?h=$1         [L]
    RewriteRule ^battlegrounds\/([a-zA-Z\-]+)(\/?)$    battleground.php?b=$1 [L]
    RewriteRule ^rotations\/([0-9\-]+)(\/?)$           rotation.php?r=$1     [L]
    RewriteRule ^sales\/([0-9\-]+)(\/?)$               sale.php?s=$1         [L]
    RewriteRule ^predictions\/([0-9\-]+)(\/?)$         predictions.php?w=$1  [L]
    RewriteRule ^subuniverses\/([a-zA-Z\-]+)(\/?)$     subuniverse.php?s=$1  [L]
    RewriteRule ^universes\/([a-zA-Z\-]+)(\/?)$        universe.php?u=$1     [L]
    RewriteRule ^events\/seasonal\/([a-zA-Z\-]+)(\/?)$ seasonal.php?s=$1     [L]
    RewriteRule ^events\/([a-zA-Z0-9\-]+)(\/?)$        event.php?e=$1        [L]
    RewriteRule ^skins\/([a-zA-Z0-9\-]+)(\/?)$         skin.php?s=$1         [L]
    RewriteRule ^mounts\/([a-zA-Z0-9\-]+)(\/?)$        mount.php?m=$1        [L]
    RewriteRule ^([a-zA-Z]+)(\/?)$                    $1.php                
</IfModule>

【讨论】:

  • 这个措辞并不完全正确......“.htaccess”根本不循环,那是一个 配置文件 。它由http服务器进程从上到下处理(以便一个循环)。如果应用任何规则并更改请求,则该过程从顶部重复。重复此操作,直到请求没有发生变化,这与“无法完成更多规则”不太一样。把它想象成一个小职员在做他的工作:他收到的每一份表格都会得到处理,如果有什么变化,他会要求确认。只有当表单返回而没有更改时,他才会感到满意
  • 事实上,这是一个很好的类比。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
  • 2017-11-21
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多