Php 如何仅在特定类型的文件存在时跳过重写,如果不存在,如何使用自定义错误处理程序?

Php 如何仅在特定类型的文件存在时跳过重写,如果不存在,如何使用自定义错误处理程序?,php,regex,.htaccess,Php,Regex,.htaccess,我有以下.htaccess功能,可以满足我的大部分需求: RewriteEngine On RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$ RewriteRule ^(.*)$ controller.php?page=$1 [NC,L,QSA] 现在,我想为文件类型指定自定义错误处理程序,而不是通用的not found消息,因此我尝试附加以下内容: RewriteCo

我有以下
.htaccess
功能,可以满足我的大部分需求:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
RewriteRule ^(.*)$ controller.php?page=$1 [NC,L,QSA]
现在,我想为文件类型指定自定义错误处理程序,而不是通用的not found消息,因此我尝试附加以下内容:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ controller.php?page=$1 [R=404,L]
但是,如果找不到该文件,它仍然不会传递到我的
controller.php
文件

我如何修改它,以便此行还确保存在该类型的特定请求文件:

RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$

更新:

以下方法可以工作,但当缺少的映像位于虚拟子路径中时,似乎会遇到问题

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
RewriteRule ^(.*)$ controller.php?page=$1 [NC,L,QSA]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ controller.php?page=error&rewritten=1&missing=$1 [NC,L,QSA]
主应用程序路径(按预期工作)

子路径-不传递所有参数

为了进行演示,
controller.php
文件可以如下所示:

<?php
print_r($_REQUEST);
从重写中排除图像、javascript等的重写条件需要将
%{REQUEST\u FILENAME}
更改为
%{REQUEST\u URI}
,其中
之后的最终重写规则-f
(文件不存在)检查,需要删除
R=404


虽然我不确定为什么会这样,或者为什么在初始重写条件下检查物理文件会导致最终重写规则出现问题,但它确实有效。正是在这种情况下,对解决方案的奖励(或分割奖励)才具有这样一个特点,因为两种解决方案都不能单独解决问题,但两者都能很好地相互补充,导致此问题的最终完整工作解决方案:)

使用4XX或5XX状态代码重写将导致HTTPd显示错误页面,而不是重写请求。您需要在
controller.php
(或pass,如参数)中检测缺失,并在那里发出错误代码。

使用4XX或5XX状态代码重写将导致HTTPd显示错误页面,而不是重写请求。您需要在
controller.php
中检测缺失(或传递,如参数),并在那里发出错误代码。

您只需更改:

RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
为此:

RewriteCond %{REQUEST_URI} !\.(jpe?g|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$ [NC]
使用
%{REQUEST\u URI}
而不是
%{REQUEST\u FILENAME}
可确保不执行现有文件检查,并且将跳过以上述扩展名结尾的任何请求


更新:在阅读了您的最终编辑后,您的意图变得更加清晰

在最终工作解决方案中,您有一个冗余规则来处理不存在的文件,原因有二:

  • 对于某些不存在的文件,客户端将看不到所有重要的
    404
    状态
  • ErrorDocument
    是处理此规则的正确指令,而不是重写规则
  • 您可以通过以下方式访问.htaccess:

    ErrorDocument 404 /controller.php?page=error&rewritten=1
    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
    RewriteRule ^(.*)$ controller.php?page=$1 [NC,L,QSA]
    

    controller.php中使用
    $\u SERVER[“REQUEST\u URI”]
    将为您提供触发404的请求URI。

    您只需更改:

    RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
    
    为此:

    RewriteCond %{REQUEST_URI} !\.(jpe?g|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$ [NC]
    
    使用
    %{REQUEST\u URI}
    而不是
    %{REQUEST\u FILENAME}
    可确保不执行现有文件检查,并且将跳过以上述扩展名结尾的任何请求


    更新:在阅读了您的最终编辑后,您的意图变得更加清晰

    在最终工作解决方案中,您有一个冗余规则来处理不存在的文件,原因有二:

  • 对于某些不存在的文件,客户端将看不到所有重要的
    404
    状态
  • ErrorDocument
    是处理此规则的正确指令,而不是重写规则
  • 您可以通过以下方式访问.htaccess:

    ErrorDocument 404 /controller.php?page=error&rewritten=1
    RewriteEngine On
    
    RewriteCond %{REQUEST_FILENAME} !\.(jpg|png|bmp|gif|css|js|map|ttf|woff|woff2|svg|eot)$
    RewriteRule ^(.*)$ controller.php?page=$1 [NC,L,QSA]
    

    controller.php中使用
    $\u SERVER[“REQUEST\u URI”]
    将为您提供触发404的请求URI。

    RewriteCond%{REQUEST\u FILENAME}-f
    跳过重写任何现有文件。您遇到这个问题的完整URL是什么?@anubhava-我不想跳过所有文件。只有特定的文件,而没有明确排除文件夹,因此这是一个软结构。
    RewriteCond%{REQUEST_FILENAME}-f
    跳过重写任何现有文件。您遇到这个问题的完整URL是什么?@anubhava-我不想跳过所有文件。只有特定的文件,没有特别排除文件夹,所以这是一个软结构。我改变了它,它似乎工作,但只从主文件夹。子文件夹仍在重写,但我在htaccess中设置的其他参数没有被传递。这很奇怪。添加了我执行此建议的演示和结果。我更改了它,它似乎有效,但仅在主文件夹中。子文件夹仍在重写,但我在htaccess中设置的其他参数没有被传递。这很奇怪。添加了我执行此建议的演示,以及结果。交换了该行,解决了出现的新问题。你的答案和Ignacio的答案结合起来解决了这个问题。事实上,你确实需要将
    ErrorDocument 404/404.php
    放在.htaccessNein的顶部。这种组合不会产生实际的404,因此我必须模拟它们。在问题中发布完整的working.htaccess,这样你们就可以看到交易内容了。实际上很酷。只需在显示自定义页面时设置适当的HTTP/1.x头,这样google就不会因为spidering将该行调出而惊慌失措,从而解决了出现的新问题。你的答案和Ignacio的答案结合起来解决了这个问题。事实上,你确实需要将
    ErrorDocument 404/404.php
    放在.htaccessNein的顶部。这种组合不会产生实际的404,因此我必须模拟它们。在问题中发布完整的working.htaccess,这样你们就可以看到交易内容了。实际上很酷。只需要在显示自定义页面时设置适当的HTTP/1.x头,这样google就不会因为爬行而惊慌失措