.htaccess - 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”)有效吗?
如果有任何兴趣,我的项目中没有“投票”文件夹。
如果有任何问题,请告诉我。
解决方案
线
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 的简单方法。
推荐阅读
- c - 如何将内存分配给指向函数中指针的指针
- scala - 如何在 spark 2.4 中使用 jdbc 运行“DELETE FROM TABLE”?
- authentication - 为什么 Cookie 只发送到 API 主机上的 API 端点?
- python-3.x - 另一个 Setup.py 错误:无法识别选项 -f
- junit - Mockito:如何测试更改私有字段值的方法?
- python - 使用 `send_keys(Keys.CONTROL + 't')` 打开一个新选项卡不起作用并且不显示任何错误
- amazon-web-services - 允许具有公共主机名的源安全组 ALB 访问
- java - 使用 OpenJDK 1.8 的 JavaFX 的 Maven 依赖项
- oracle - 如何在批量收集循环中进行条件处理?
- javascript - 有没有一种方法可以检查数组中是否有任何值?