首页 > 解决方案 > 重写 htaccess 规则不完美

问题描述

我有一堆不同类别的规则,这里是一个类别......

RewriteRule ^words/$ /words/publicWordLists.php [L]
RewriteRule ^words/([A-Za-z]+$) /words/word.php?word=$1 [L]
RewriteRule ^([A-Za-z0-9-]+)/words/$ /words/userWordLists.php?username=$1 [L]
RewriteRule ^([A-Za-z0-9-]+)/words/([A-Za-z0-9-]+$) /words/list.php?username=$1&url=$2 [L]

这很有效,因为如果你去 words/ 你从 publicWordsList.php 获取内容 - 但是 - 如果你直接去 /words/publicWordLists.php - 它不会重定向回 words/

那么如何在保持我最初意图的同时防止人们直接访问这些页面呢?

标签: php.htaccess

解决方案


您可以在 301 将“丑陋”文件系统路径重定向到所需 URL 的文件顶部创建“重定向”。但是,您需要小心重定向循环,因为稍后的重写会再次重写 URL。

例如:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^words/publicWordLists\.php$ /words/ [R=302,L]

对环境变量的检查REDIRECT_STATUS可以防止重定向循环,因为它只查看初始请求,而不是重写的请求。REDIRECT_STATUS最初为空,但在第一次成功重写后设置为“200”。

仅在确认一切正常后才302将(临时)更改为(永久) - 以避免潜在的缓存问题。301

您的其他包含查询字符串的指令有点棘手,因为它们需要额外的条件。查询字符串不是RewriteRule 模式匹配的 URL 路径的一部分。

例如:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^word=([a-zA-Z]+)$
RewriteRule ^words/word\.php$ /words/%1 [QSD,R=302,L]

以上重定向/word/word.php?word=<something>/words/<something>.

%1是对前面RewriteCond指令中捕获的 URL 参数值的反向引用。该QSD标志是从重定向请求中删除原始查询字符串所必需的。

更新:标志QSD是 Apache 2.4+。如果您仍在使用 Apache 2.2,那么您可以将 a 附加?替换字符串(本质上是一个空的查询字符串)的末尾,以便从重定向的 URL 中删除查询字符串。例如,在Apache 2.2上,您将需要这个:

RewriteRule ^words/word\.php$ /words/%1? [R=302,L]

推荐阅读