首页 > 解决方案 > Mod_rewrite 仅适用于某些文件夹名称

问题描述

语境

我正在使用 mod_rewrite 使我的链接更适合 SEO。我为我的页面制定了以下规则expanded_debate.php

Options -MultiViews

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^poll/([0-9a-zA-Z_-]+)/([0-9]+) expanded_debate.php?poll_title=$1&pollid=$2 [NC,QSA,L]

当我在 URL 中输入此格式时(例如 poll/filename/10),我收到 404 错误:

Object not found!
The requested URL was not found on this server. If you entered the URL manually please check your spelling and try again.

If you think this is a server error, please contact the webmaster.

Error 404
localhost
Apache/2.4.46 (Unix) OpenSSL/1.1.1h PHP/7.4.12 mod_perl/2.0.11 Perl/v5.32.0

但是,当我将第一个文件夹名称更改为某些单词时,例如“debate”和“expanded_debate”(但不是“expandedebate”),文件会在页面刷新后加载。例如:

RewriteRule ^debate/([0-9a-zA-Z_-]+)/([0-9]+) expanded_debate.php?poll_title=$1&pollid=$2 [NC,QSA,L]

工作正常。

我有一个较旧的 .htaccess 文件,标题为“.htaccess11”,其中包含以下信息,以备不时之需:

#forbids users from going to forbidden pages
IndexIgnore *

Options -Indexes
RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/cpanel-dcv/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/(?:\ Ballot169)?
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

#404 error directions
ErrorDocument 404 /404.php

问题

知道为什么在使用 mod_rewrite 时只有第一个文件夹位置中的某些术语(上面示例中的“^debate”)有效吗?

如果有任何兴趣,我的项目中没有“投票”文件夹。

如果有任何问题,请告诉我。

标签: .htaccessmod-rewrite

解决方案


线

RewriteCond %{REQUEST_FILENAME}\.php -f

意思是“获取请求的 URL,以正常方式将其映射到完整的本地路径,附加.php到结果路径,然后仅当修改后的路径存在现有常规文件时才处理以下重写规则”。

例如,只有在相关位置存在名为“poll/filename/10.php”的文件时,才会重写 URL“poll/filename/10”。

由于该AcceptPathInfo指令的值显然设置为On,因此如果存在名为“poll.php”或“poll/filename.php”的文件,也将满足此条件。这就是当您将“poll”更改为“debate”或“expanded_debate”时重写规则起作用的原因——存在名为“debate.php”和“expanded_debate.php”的现有文件。

无论如何,听起来这种行为不是预期的。删除-f条件应该会产生预期的结果。或者,为了防止重写规则使现有文件无法访问,您可以将其替换为:

RewriteCond %{REQUEST_FILENAME} !-f
  • 感叹号否定-f测试:“仅当此文件不存在时才继续”

  • 如果您正在使用%{REQUEST_FILENAME}服务器变量(任何地方),您应该知道该AcceptPathInfo指令将如何影响这一点,并考虑在同一个 .htaccess 文件中显式设置该指令。

  • 如果Options +MultiViews有效,则%{REQUEST_FILENAME}无论扩展名是否包含在请求中,都将匹配现有文件(GET /foo将匹配现有文件“foo.php”、“foo.html”等)。并且GET /foo.php在任何情况下都会匹配。因此,从原始规则中省略字符串“\.php”。

  • 其他配置也可能会产生影响。重要的一点是,与 不同的是%{REQUEST_URI},它%{REQUEST_FILENAME}调用了 Apache 否则会将 URL 转换为本地路径的所有处理。

(资源)


注意:虽然我不认为这是这里的意图,但您实际上可能想要测试本地文件是否存在作为此规则的一部分。您可以使用 aRewriteCond检查给定投票的后端数据文件是否已手动创建,如果没有则默认返回 404。这将是一种防止用户随意制作自己的投票 URL 的简单方法。


推荐阅读