您能看出我的.htaccess 有什么错误吗?

您能看出我的.htaccess 有什么错误吗?

我已成功创建了一个.htaccess可以完成我想要的操作的文件(请参阅代码块后的解释和问题):

<IfModule mod_rewrite.c>

RewriteEngine On

#1 If the requested file is not url-mapper.php (to avoid .htaccess loop)
RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.(.*) [OR]
RewriteCond %{REQUEST_URI} \.php.*$ [NC]

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$

#Then serve the URI via the mapper
RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

</IfModule>

这是应该.htaccess做的:

  1. 规则1检查所请求的文件是否不存在url-mapper.php(以避免无限重定向循环)。此文件将始终位于域的根目录中。

  2. 规则#2必须.htaccess仅捕获不以扩展名结尾的 URL(www.example.com--> 捕获 | www.example.com/catch-me--> 捕获 | www.example.com/dont-catch.me--> 不捕获)以文件结尾的 URL .php\*.php,,,,...)。.php4.php5.php123

  3. 规则#3一些目录(及子目录)可以从中排除.htaccess(在本例中为/seo-urls/excluded1/seo-urls/excluded2)。

  4. 最后,.htaccess向映射器提供GET 参数名为uri包含请求的 URI。

即使我测试过并且一切正常,我也想知道我所做的是否正确(以及这是否是“最佳”方法)。我从这个“项目”中学到了很多东西,但我仍然认为自己是.htaccess正则表达式的初学者,因此在投入生产之前我想再三检查一下……

答案1

2a 将允许 /some.dir/file,因为中间有“.” 。您可能需要类似的东西!\..[1,3],这取决于您的文件/目录结构。

在 RewriteRules 中,使用替换匹配而不是变量名是正常的:
RewriteRule (.*) /seo-urls/url-mapper.php?uri=$5 [L,QSA]
注意,这是$5因为您当前在所有条件中都有匹配模式。

答案2

<IfModule mod_rewrite.c>

不需要<IfModule>包装器。请参阅网站管理员堆栈上的这个问题: https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

#1 If the requested file is not url-mapper.php (to avoid .htaccess loop)
RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$

无需使用负向后视 ( (?<!)。最好只使用否定正则表达式。即带前缀!。例如:(!^/url-mapper\.php$即。不是“/url-mapper.php”)并检查REQUEST_URI(完整 URL 路径)而不是REQUEST_FILENAME(绝对文件系统路径)。

但是,您声明“此文件将始终位于域的根目录”,但您正在重写/seo-urls/url-mapper.php- 它不在域的根目录。

因此,严格来说应该这样写:

RewriteCond %{REQUEST_URI} !^/seo-urls/url-mapper\.php$

url-mapper.php除非您确信系统上只有一个文件,否则正则表达式可以简化为!/url-mapper\.php$

或者,检查一下RewriteRule 图案相反(因为你没有对RewriteRule 图案目前)。这将是略有不同更高效。

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.(.*) [OR]
RewriteCond %{REQUEST_URI} \.php.*$ [NC]

第一个条件太笼统了 - 它捕获 URL 路径中任何只包含点的 URL,而不仅仅是文件扩展名。也不需要捕获子模式。假设文件扩展名介于 2 到 4 个字符之间,那么像这样的模式!\.\w{2,4}$会更准确地捕获文件扩展名。

正则表达式通常应尽可能严格。第二个条件是火柴 .php扩展可以变得更加严格,目前它匹配.php 任何地方在 URL 路径中。例如:\.php\d{0,4}$- 尽管实际上,后面可能最多只有 1 位数字.php,所以\.php\d?$可能更好。

我还想问一下NC这里是否真的需要 (不区分大小写) 标志。你真的需要匹配.PHP.PhP

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$

好的,但结尾(/.*)?$是多余的。你匹配的是任何以“等”开头的/seo-urls/excluded1内容。此外,不需要对斜杠进行反斜杠转义(奇怪的是,你转义了中间的斜杠,但没有转义其他两个斜杠)。

#Then serve the URI via the mapper
RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

好的,尽管正则表达式.*(匹配所有内容)可以简化为^- 它对所有内容都成功,但实际上并不匹配任何内容 - 但这就是您所需要的。

不过,我在顶部提到了url-mapper.phpRewriteRule 图案而是。因此,应该这样写:

RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

RewriteRule 图案在任何条件之前都首先被处理,因此最好在指令中执行你能做的事情RewriteRule,而不是将其分离到另一个条件中。

概括

综合以上几点,我们可以得出:

RewriteEgnine On

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.\w{2,4}$ [OR]
RewriteCond %{REQUEST_URI} \.php\d?$

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)

#Then serve the URI via the mapper
RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [QSA,L]

相关内容