1

真的很难过,因为形式和语法看起来都不错。

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
  • 通过重定向到谷歌验证 request_uri 是否匹配
  • 仅使用第一个 Cond 时无法获得 410
  • (仅使用第一个 Cond 时,服务器服务 404,而不是 410)
  • (同时使用 Conds,服务器服务 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]

更新二

对白先生的回应:

呃,同样的症状。对于过时的 css/js,可能不得不忍受 googlebot 达到 404s 而不是所需的 410。从长远来看,可能没什么大不了的。

感谢您的 request_uri 测试重定向。在这些测试中一切正常。在 var= rewrite URL 中按预期返回页面名称等。

至此,我想一定是对文件类型扩展名相关的404s的一些内部处理。请参阅下面的线索。我有 Prestashop 购物车软件,它必须在文件类型上强制 404。

这将重定向到谷歌(确认模式匹配):

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,但我看不到任何其他解释。我可以深入研究它,也许可以在控制器中找到正在执行此操作的位置。不过也得休息一下。

4

2 回答 2

1

我无法确定为什么服务器配置或站点代码会强制 htaccess 中的“410 Gone”响应指令被 404 响应覆盖,因此必须执行类似的操作告诉 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');

更新我

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

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

白先生!我在您在 Stack Exchange 上的一篇帖子中找到了这个解决方案。

于 2019-05-31T16:12:56.787 回答
1

这不是一个真正可靠的答案,更多的是试图帮助调试它并消除一些神话......

我已经验证使用phpinfo()包含REQUEST_URI前导斜杠

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

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

所以,这就是我问你是否有其他 mod_rewrite 指令的原因。你很可能发生了冲突。如果另一个指令重写 URL,则条件将永远不会匹配(尽管 PHP 超全局建议它应该)。

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

这个指令当然应该放在.htaccess文件的顶部,以避免 URL 被更早地重写。当与 a (除 a 以外的任何东西)一起使用时,该L标志实际上是多余的- 在这种情况下是隐含的。R=4103xx

然后我将结果更改为“抛出 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文件以避免对错误文档的内部子请求。

于 2019-05-31T01:04:46.170 回答