REQUEST_URI与显式路径和文件名不匹配

时间:2019-05-30 22:18:33

标签: .htaccess mod-rewrite url-rewriting request-uri

真的很困惑,因为形式和语法看起来还不错。

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]

UPDATE II

对怀特先生的回应:

哦,同样的症状。可能必须与googlebot一起使用404,而不是过时的CSS / JS所需的410。从长远来看,可能没什么大意了。

谢谢您的request_uri测试重定向。在这些测试中,一切正常。在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.)

这将继续返回404而不是410:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.txt$ - [NC,R=410]

作为对照测试,这将返回410:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^.*$ - [NC,R=410]

如果在上述失败的测试中文件类型为css,则不会调用我的自定义404控制器。我只是收到一个简单的404响应,没有包含我所有网站模板的自定义404。

例如:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^testmee\.css$ - [NC,R=410]

恐怕我浪费了一些时间。我很抱歉。我从没想过Prestashop的代码会基于文件类型强制使用404,但是我看不到任何其他解释。我可以深入研究它,也许可以在Controllers中找到正在做的事情。不过要休息一下。

2 个答案:

答案 0 :(得分:1)

这并不是一个真正的答案,更多的是试图帮助调试并打破一些神话的事情……

  

我已使用phpinfo()验证了REQUEST_URI包含斜杠

是的,REQUEST_URI Apache服务器变量确实包含前导斜杠。它包含完整的URL路径。

但是,REQUEST_URI Apache服务器变量不一定与$_SERVER['REQUEST_URI'] PHP超全局变量相同-实际上,它们根本不是一回事。这些变量之间存在一些显着差异(在某些方面,它们使用相同的名称可能有点不幸)。值得注意的是,PHP超全局包含请求中的初始URL,并包含查询字符串(如果有),并且未进行%解码。而同名的Apache服务器变量包含重写的URL (不一定是请求的URL),并且不包含查询字符串,并且经过%解码。

因此,这就是为什么我问您是否还有其他mod_rewrite指令。您很可能发生了冲突。如果另一个指令重写了URL,则该条件将永远不会匹配(尽管PHP超全局变量建议这样做)。

  

如果我将其放在顶部,Last标志将结束该行程的处理,返回410

此伪指令肯定应该放在.htaccess文件的顶部,以避免该URL被更早地重写。与L(除R=410以外的其他任何符号)一起使用时,3xx标志实际上是多余的–在这种情况下隐含。

  

然后,我将结果更改为“抛出410”,并抛出404。

这肯定是由服务器端覆盖引起的。但是在其他情况下您也可以抛出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文件,以避免对错误文档的内部子请求。

答案 1 :(得分:0)

我无法确定为什么服务器配置或站点代码会强制htaccess中的“ 410 Gone”响应指令被404响应覆盖,因此必须执行类似this的操作来告诉googlebot停止寻找定期清除的CSS / JS文件(并在重新生成时重命名)。

.htaccess中的

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule v_(.*)_(.*)$ /410response.php [L]

放在410response.php中的根目录中:

<?php header($_SERVER['SERVER_PROTOCOL'].' 410 Gone');

更新我

由于服务器显然具有自定义的410文档(显然路由到404),因此服务器强行尝试将htaccess用于410指令时的404响应。添加了一个指令以防止随后正确允许使用htaccess在RewriteRule中返回410以进行模式匹配。 (我以为我昨天已经检查了一下是否可行,因为@MrWhite在上面的回答中表示要控制可能具有自定义410的服务器;今天进行检查时,它确实起作用并指出服务器410- -404重定向覆盖了我的410指令。)

ErrorDocument 410 default
RewriteRule test\.txt$ - [NC,R=410]

怀特先生!我在Stack Exchange上的one of your posts中找到了该解决方案。