3

我的自定义配置文件中有以下代码。

<Directory "/www">
    Options Indexes FollowSymLinks
    AllowOverride All
    <FilesMatch "\.phps$">
        SetHandler application/x-httpd-php-source
    </FilesMatch>
    ErrorDocument 403 "Please disable proxies to view content."
    RewriteEngine On
    RewriteRule ^(.*\.php)s$ $1 [H=application/x-httpd-php-source]
    RewriteRule ^faq/(\w+)/(\d+)/?$ faq.php?code=$1&num=$2 [NC]
</Directory>

现在,当我浏览到类似/index.phpsor的网页时/some/other/dir/and/file.phps,我在浏览器中收到 404 错误,并且在 apache 的错误日志中记录了以下内容:

[<date>] [:error] [pid 15154:tid 3024079728] [client <IP>] script 'redirect:/request/get_req.php' not found or unable to stat
[<date>] [:error] [pid 15152:tid 2914974576] [client <IP>] script 'redirect:/index.php' not found or unable to stat

什么可能导致此问题?另外,请注意第二个RewriteRuleforfaq/..运行良好。我在每个目录的基础文件中还有一些重写规则,htaccess并且所有这些规则都可以正常工作。

我使用的服务器版本是Apache/2.4.9 (Unix)


在听取了coveneranubhava的建议后;我将conf文件更新为:

<VirtualHost *:80>
    DocumentRoot "/www"
    <FilesMatch "\.phps$">
        SetHandler application/x-httpd-php-source
    </FilesMatch>
    LogLevel warn
</VirtualHost>
<Directory "/www">
    Options Indexes FollowSymLinks
    AllowOverride All
    RewriteEngine On
    # RewriteRule ^(.*\.php)s$ %{DOCUMENT_ROOT}/$1 [H=application/x-httpd-php-source]
    # RewriteRule ^/?(.*\.php)s$ %{DOCUMENT_ROOT}/$1 [H=application/x-httpd-php-source]
    # RewriteRule ^(.*\.php)s$ $1 [H=application/x-httpd-php-source]
    RewriteRule ^(.*\.php)s$ %{DOCUMENT_ROOT}/$1 [H=application/x-httpd-php-source]
    RewriteRule ^faq/(\w+)/(\d+)/?$ faq.php?code=$1&num=$2 [NC]
</Directory>

但是 php 源的处理程序仍在记录相同的错误:

[<date>] [:error] [pid 17586:tid 2956938096] [client <IP>] script 'redirect:/index.php' not found or unable to stat
4

2 回答 2

2

您不能执行每个目录替换并设置处理程序 (H=),因为 mod_rewrite 如何执行每个目录替换的机制需要将处理程序设置为 mod_rewrite 本身。

每个目录的替换做两件事:

  • 将处理程序设置为特殊的 mod_rewrite 处理程序
  • 在映射文件名前加上重定向:

因此,通过设置 H=,您将吹走 1,并在错误消息中看到 apache 的核心试图将“redirect:/...”作为文件名来处理。

这是每个目录重写的记录限制,并且此 H= 标志不起作用,但并不是说它破坏了重写:

当在同一轮重写处理期间执行替换(“-”除外)时,更改与请求关联的元数据的标志(T=、H=、E=)在每个目录和 htaccess 上下文中没有影响。

您应该将重写指令从 <Directory> 上下文中拉出,并将前导前缀 (/ ?) 恢复到您的第一个参数,并确保您的第二个参数替换是绝对 URL 路径而不是相对 URL 路径。在目录上下文之外,不需要内部重定向,一切都简单得多。

例如,使其对非 per-dir 上下文安全:

RewriteRule ^(.*\.php)s$ %{DOCUMENT_ROOT}/$1 [H=application/x-httpd-php-source]
RewriteRule ^/faq/(\w+)/(\d+)/?$ /faq.php?code=$1&num=$2 [NC]

在这种情况下,您的 URL 被映射到一个文件并设置了处理程序,没有将 URL 重新引入 Apache 处理,因为它是一个简单的 uri->file 映射。我

于 2014-06-06T12:10:15.830 回答
2

要使其工作,您需要将此代码片段从<Directory>容器中取出并将其放在<VirtualHost>块中:

<FilesMatch "\.phps$">
    SetHandler application/x-httpd-php-source
</FilesMatch>
RewriteEngine On
RewriteRule ^(.*\.php)s$ $1 [H=application/x-httpd-php-source]

它在块中工作的原因<VirtualHost>是因为重写发生在 apache 处理的早期阶段,即per-server上下文。但是,当它发生在per-dir上下文中时,它发生在后期阶段,并导致请求在替换后重新启动。如果在每个目录上下文中进行了替换,则会使用新 URL 发出一个新的内部子请求,这会重新启动请求阶段的处理。

有关更多详细信息,请参阅此mod_rewrite 技术参考

我的VirtualHost条目:

<VirtualHost *:80>
   <FilesMatch "\.phps$">
        SetHandler application/x-httpd-php-source
    </FilesMatch>
    ErrorDocument 403 "Please disable proxies to view content."
    RewriteEngine On
    RewriteRule ^([^.]+\.php)s$ $1 [H=application/x-httpd-php-source,NC]
</VirtualHost>
于 2014-06-06T22:25:58.683 回答