Mod_rewrite 仅使用特定文件夹名称

Mod_rewrite only working with certain folder names

上下文

我正在使用 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=&pollid= [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

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

RewriteRule ^debate/([0-9a-zA-Z_-]+)/([0-9]+) expanded_debate.php?poll_title=&pollid= [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附加到结果路径,然后只在有的情况下才处理下面的重写规则修改路径中的现有常规文件。

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

由于 AcceptPathInfo 指令的值显然设置为 On,如果存在名为“poll.php”或“[=”的现有文件,也将满足此条件70=].php”。这就是为什么当您将“投票”更改为“辩论”或“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} 调用 all Apache 否则会将 URL 转换为本地路径的处理。

(source)


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