REQUEST_URI 不匹配显式路径和文件名
REQUEST_URI not matching explicit path and filename
真的很困惑,因为形式和语法看起来都不错。
REQUEST_URI 的 RewriteCond 与显式路径和文件名不匹配。隔离时,REQUEST_FILENAME 的 RewriteCond 匹配得很好。我已经使用 phpinfo() 验证了 REQUEST_URI 包含前导斜杠,并且在没有前导斜杠的情况下也进行了测试。
这里的目标是知道请求是针对这个文件的,如果不存在,则抛出 410。
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
我不想省略第一个 Cond,因为我只想对少数与此类似的文件执行此操作。
更新我
正在尝试进行最终测试。测试设置:
- testmee.txt不存在
- 请求是针对根
中的 testmee.txt
- 通过重定向到 google
验证了 request_uri 匹配
- 仅使用第一个 Cond 时无法获得 410
- (仅使用第一个 Cond 时,服务器提供 404,而不是 410)
- (使用两个条件,服务器提供 404,而不是 410)
- 仅使用第二个 Cond 时可以获得 410
RewriteCond %{REQUEST_URI} ^/testmee\.txt$
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
对比
#RewriteCond %{REQUEST_URI} ^/testmee\.txt$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
更新二
对怀特先生的回应:
呃,同样的症状。可能不得不忍受 google 机器人点击 404 而不是过时的 css/js 所需的 410。长 运行 没什么大不了的。
感谢您的 request_uri 测试重定向。在这些测试中一切正常。页面名称等按预期 returned,在 var= 中重写 URL.
在这一点上,我认为这一定是对与文件类型扩展名相关的 404 的一些内部处理。请参阅下面的线索。我有 Prestashop 购物车软件,它必须在文件类型上强制显示 404。
这将重定向到 google(以确认模式匹配):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ http://www.google.com/ [L]
(L flag is needed or else other Rules further down will interfere.)
这将继续 return 404 而不是 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ - [NC,R=410]
作为对照测试,这将 return 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ - [NC,R=410]
如果在上述失败测试中文件类型为 css,则不会调用我的自定义 404 控制器。我只收到一个普通的 404 响应,w/o 包含我所有网站模板的自定义 404。
例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.css$ - [NC,R=410]
恐怕我已经浪费了你的一些时间。我很抱歉。我从没想过 Prestashop 的代码会根据文件类型强制 404,但我看不到任何其他解释。我可以深入研究它,也许会在控制器中找到执行此操作的位置。不过要休息一下。
这不是一个真正可靠的答案,更多的是尝试帮助调试这个问题并消除一些神话...
I have verified using phpinfo()
that REQUEST_URI
contains the leading slash
是的,REQUEST_URI
Apache 服务器变量确实包含前导斜线。它包含完整的 URL-path.
但是,REQUEST_URI
Apache 服务器变量不一定与 $_SERVER['REQUEST_URI']
PHP 超全局变量相同 - 事实上,它们根本不是一回事。这些变量之间存在一些显着差异(在某些方面,它们共享相同的名称可能有点不幸)。值得注意的是,PHP 超全局包含请求中的初始 URL 并包含查询字符串(如果有)并且未进行 % 解码。而同名的 Apache 服务器变量包含 重写的 URL(不一定是请求的 URL)并且不包含查询字符串并且是 %-decoded .
所以,这就是我问您是否还有其他 mod_rewrite 指令的原因。你们很可能发生了冲突。如果另一个指令重写 URL,则条件永远不会匹配(尽管 PHP 超全局建议它应该匹配)。
It seemed that if I put this at the top, the Last flag would end processing for that trip through, return the 410
这个指令当然应该放在 .htaccess
文件的顶部,以避免 URL 被更早地重写。当与 R=410
(除 3xx
之外的任何东西)一起使用时,L
标志实际上是多余的 - 在这种情况下它是隐含的。
Then I change the result to be "throw a 410" and it throws a 404.
这肯定是由 server-side 覆盖引起的。但是你可以在其他情况下抛出 410,所以这似乎排除了这种可能性。但是,如果有疑问,您可以在 .htaccess
中重置错误文档(除非您已经在使用自定义错误文档):
ErrorDocument 410 default
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
虽然这对规则的行为方式并没有真正的影响,但您不需要第一个 RewriteCond
指令来检查 REQUEST_URI
。您应该改为在 RewriteRule
模式 中进行此检查(这会更有效,因为它首先被处理)。例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$ - [NC,R=410]
NC
标志应该是多余的。
不过,与现有指令的冲突仍然是最可能的原因。删除所有其他指令。您是否仍然看到相同的行为?
您可以测试 REQUEST_URI
服务器变量的值。您可以发出重定向并将 REQUEST_URI
作为 URL 参数传递,或者设置环境变量(但每次重写都需要注意 REDIRECT_<var>
)。
例如,在您 .htaccess
的顶部(或您尝试此操作的任何地方):
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ /test.php?var=%{REQUEST_URI} [NE,R,L]
创建了一个虚拟 test.php
文件以避免对错误文档的内部子请求。
我无法确定为什么服务器配置或站点代码会强制 htaccess 中的“410 Gone”响应指令被 404 响应覆盖,因此必须执行类似 this 的操作来告诉 googlebot 停止寻找 CSS/JS 定期清除(并在重新生成时重命名)的文件。
在 .htaccess 中:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule v_(.*)_(.*)$ /410response.php [L]
in 410response.php 放在根目录中:
<?php header($_SERVER['SERVER_PROTOCOL'].' 410 Gone');
更新我
尝试使用 htaccess 作为 410 指令时的 404 响应被服务器强制执行,因为服务器显然有一个自定义 410 文档,显然路由到 404。添加一个指令以防止然后正确允许使用htaccess 的 return 410 用于 RewriteRule 中的模式匹配。 (我以为我昨天已经检查过这是否可行,因为@MrWhite 在上面的回答中说要控制可能具有自定义 410 的服务器;今天进行此检查时,它确实有效并表明服务器 410-to -404 重定向覆盖了我的 410 指令。)
ErrorDocument 410 default
RewriteRule test\.txt$ - [NC,R=410]
怀特先生!我在 Stack Exchange 的 one of your posts 中找到了这个解决方案。
真的很困惑,因为形式和语法看起来都不错。
REQUEST_URI 的 RewriteCond 与显式路径和文件名不匹配。隔离时,REQUEST_FILENAME 的 RewriteCond 匹配得很好。我已经使用 phpinfo() 验证了 REQUEST_URI 包含前导斜杠,并且在没有前导斜杠的情况下也进行了测试。
这里的目标是知道请求是针对这个文件的,如果不存在,则抛出 410。
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
我不想省略第一个 Cond,因为我只想对少数与此类似的文件执行此操作。
更新我
正在尝试进行最终测试。测试设置:
- testmee.txt不存在
- 请求是针对根 中的 testmee.txt
- 通过重定向到 google 验证了 request_uri 匹配
- 仅使用第一个 Cond 时无法获得 410
- (仅使用第一个 Cond 时,服务器提供 404,而不是 410)
- (使用两个条件,服务器提供 404,而不是 410)
- 仅使用第二个 Cond 时可以获得 410
RewriteCond %{REQUEST_URI} ^/testmee\.txt$
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
对比
#RewriteCond %{REQUEST_URI} ^/testmee\.txt$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ - [R=410,L]
更新二
对怀特先生的回应:
呃,同样的症状。可能不得不忍受 google 机器人点击 404 而不是过时的 css/js 所需的 410。长 运行 没什么大不了的。
感谢您的 request_uri 测试重定向。在这些测试中一切正常。页面名称等按预期 returned,在 var= 中重写 URL.
在这一点上,我认为这一定是对与文件类型扩展名相关的 404 的一些内部处理。请参阅下面的线索。我有 Prestashop 购物车软件,它必须在文件类型上强制显示 404。
这将重定向到 google(以确认模式匹配):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ http://www.google.com/ [L]
(L flag is needed or else other Rules further down will interfere.)
这将继续 return 404 而不是 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ - [NC,R=410]
作为对照测试,这将 return 410:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ - [NC,R=410]
如果在上述失败测试中文件类型为 css,则不会调用我的自定义 404 控制器。我只收到一个普通的 404 响应,w/o 包含我所有网站模板的自定义 404。
例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.css$ - [NC,R=410]
恐怕我已经浪费了你的一些时间。我很抱歉。我从没想过 Prestashop 的代码会根据文件类型强制 404,但我看不到任何其他解释。我可以深入研究它,也许会在控制器中找到执行此操作的位置。不过要休息一下。
这不是一个真正可靠的答案,更多的是尝试帮助调试这个问题并消除一些神话...
I have verified using
phpinfo()
thatREQUEST_URI
contains the leading slash
是的,REQUEST_URI
Apache 服务器变量确实包含前导斜线。它包含完整的 URL-path.
但是,REQUEST_URI
Apache 服务器变量不一定与 $_SERVER['REQUEST_URI']
PHP 超全局变量相同 - 事实上,它们根本不是一回事。这些变量之间存在一些显着差异(在某些方面,它们共享相同的名称可能有点不幸)。值得注意的是,PHP 超全局包含请求中的初始 URL 并包含查询字符串(如果有)并且未进行 % 解码。而同名的 Apache 服务器变量包含 重写的 URL(不一定是请求的 URL)并且不包含查询字符串并且是 %-decoded .
所以,这就是我问您是否还有其他 mod_rewrite 指令的原因。你们很可能发生了冲突。如果另一个指令重写 URL,则条件永远不会匹配(尽管 PHP 超全局建议它应该匹配)。
It seemed that if I put this at the top, the Last flag would end processing for that trip through, return the 410
这个指令当然应该放在 .htaccess
文件的顶部,以避免 URL 被更早地重写。当与 R=410
(除 3xx
之外的任何东西)一起使用时,L
标志实际上是多余的 - 在这种情况下它是隐含的。
Then I change the result to be "throw a 410" and it throws a 404.
这肯定是由 server-side 覆盖引起的。但是你可以在其他情况下抛出 410,所以这似乎排除了这种可能性。但是,如果有疑问,您可以在 .htaccess
中重置错误文档(除非您已经在使用自定义错误文档):
ErrorDocument 410 default
RewriteCond %{REQUEST_URI} ^/dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$ RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ - [R=410,L]
虽然这对规则的行为方式并没有真正的影响,但您不需要第一个 RewriteCond
指令来检查 REQUEST_URI
。您应该改为在 RewriteRule
模式 中进行此检查(这会更有效,因为它首先被处理)。例如:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^dir1/dir2/dir3/v_9991_0726dd5b5e8dd67a214c0c243436d131_all\.css$ - [NC,R=410]
NC
标志应该是多余的。
不过,与现有指令的冲突仍然是最可能的原因。删除所有其他指令。您是否仍然看到相同的行为?
您可以测试 REQUEST_URI
服务器变量的值。您可以发出重定向并将 REQUEST_URI
作为 URL 参数传递,或者设置环境变量(但每次重写都需要注意 REDIRECT_<var>
)。
例如,在您 .htaccess
的顶部(或您尝试此操作的任何地方):
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ /test.php?var=%{REQUEST_URI} [NE,R,L]
创建了一个虚拟 test.php
文件以避免对错误文档的内部子请求。
我无法确定为什么服务器配置或站点代码会强制 htaccess 中的“410 Gone”响应指令被 404 响应覆盖,因此必须执行类似 this 的操作来告诉 googlebot 停止寻找 CSS/JS 定期清除(并在重新生成时重命名)的文件。
在 .htaccess 中:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule v_(.*)_(.*)$ /410response.php [L]
in 410response.php 放在根目录中:
<?php header($_SERVER['SERVER_PROTOCOL'].' 410 Gone');
更新我
尝试使用 htaccess 作为 410 指令时的 404 响应被服务器强制执行,因为服务器显然有一个自定义 410 文档,显然路由到 404。添加一个指令以防止然后正确允许使用htaccess 的 return 410 用于 RewriteRule 中的模式匹配。 (我以为我昨天已经检查过这是否可行,因为@MrWhite 在上面的回答中说要控制可能具有自定义 410 的服务器;今天进行此检查时,它确实有效并表明服务器 410-to -404 重定向覆盖了我的 410 指令。)
ErrorDocument 410 default
RewriteRule test\.txt$ - [NC,R=410]
怀特先生!我在 Stack Exchange 的 one of your posts 中找到了这个解决方案。