首页 > 解决方案 > htaccess 未针对一个 URL 进行评估

问题描述

我的网络服务器目前有一个有趣的问题,我找不到解决方案,希望能得到您的帮助。

我已经在 Arch Linux 上设置了一个 Apache 服务器,并且正在使用 VirtualDocumentRoot 来创建“开发域”。配置文件如下所示:

ServerName localhost
<VirtualHost *:80>
    UseCanonicalName Off
    DocumentRoot /srv/http/
    ServerName localhost

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Directory /srv/http/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

    ErrorLog /var/log/httpd/error_log
    LogLevel warn rewrite:trace3
    CustomLog /var/log/httpd/access_log combined
</VirtualHost>
<VirtualHost *:80>
    UseCanonicalName Off
    VirtualDocumentRoot /srv/http/%-2/webroot/
    VirtualScriptAlias /srv/http/%-2/cgi-bin/
    DocumentRoot /srv/http/

    ServerAlias *.localhost

    <Directory />
        Options FollowSymLinks
        AllowOverride None
    </Directory>

    <Directory /srv/http/>
        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

    ErrorLog /var/log/httpd/error_log
    LogLevel warn rewrite:trace3

    LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
    CustomLog /var/log/httpd/access_log vcommon

</VirtualHost>

我在服务器上的文件结构是这样建立的:

root folder (/srv/http/)
 |- project folder (e.g. projectname)
     |- some project stuff (e.g. nbproject)
     |- some project stuff (e.g. vendor)
     |- public folder (webroot)

因此,如果我访问 http://localhost,它将显示所有项目。单击一个项目我可以看到所有文件夹并单击“webroot”我将看到该项目的最终主页。

由于 VirtualDocumentRoot 配置,我还可以直接访问http://projectname.localhost,它将提供 /srv/http/projectname/webroot 的内容,从而可以像在“真实条件”中一样测试网页。

对于其中一个项目,我创建了一个 MVC 系统,它像 Wordpress 一样构建。如果你调用类似http://projectname.localhost/foo/bar的东西,服务器应该提供文件 /srv/http/projectname/webroot/index.php 并将 foo 和 bar 作为参数传递给索引文件。这是通过将 .htaccess 文件放入包含以下内容的 webroot 文件夹来完成的:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

这适用于两个版本。因此 http://localhost/projectname/webroot/foo/bar 和http://projectname.localhost/foo/bar提供完全相同的结果。

现在有趣的事情来了:

如果在这个 MVC 页面上用户想要访问一个不存在的主题,他将被重定向到页面http://projectname.localhost/error/404。但是这个页面不能调用!我没有显示花哨的错误页面,而是得到了服务器内部错误页面。文件夹“错误”实际上并不存在。这没关系,因为 .htaccess 仍应为 index.php 提供服务。但是 .htaccess 没有被执行。

所以我做了一些测试并得到了这个结果(在括号中你可以看到重定向是否有效以及服务器回复状态代码):

仅当我使用 VirtualDocumentRoot 版本并且 URL 子路径以“错误”开头并且路径以某种方式继续时才会出现问题。

我检查了日志文件,并且所有正常的 access.log 看起来像这样:

projectname.localhost 127.0.0.1 - - [02/Oct/2020:06:00:00 +0000] "GET /something/404 HTTP/1.1" 200 -

error.log 看起来像这样:

[Fri Oct 02 06:00:00.919667 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] add path info postfix: /srv/http/projectname/webroot/something -> /srv/http/projectname/webroot/something/404
[Fri Oct 02 06:00:00.919721 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] strip per-dir prefix: /srv/http/projectname/webroot/something/404 -> something/404
[Fri Oct 02 06:00:00.919736 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] applying pattern '^' to uri 'something/404'
[Fri Oct 02 06:00:00.919761 2020] [rewrite:trace2] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] rewrite 'something/404' -> 'index.php'
[Fri Oct 02 06:00:00.919773 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] add per-dir prefix: index.php -> /srv/http/projectname/webroot/index.php
[Fri Oct 02 06:00:00.919784 2020] [rewrite:trace2] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] strip document_root prefix: /srv/http/projectname/webroot/index.php -> /index.php
[Fri Oct 02 06:00:00.919793 2020] [rewrite:trace1] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883c5440/initial] [perdir /srv/http/projectname/webroot/] internal redirect with /index.php [INTERNAL REDIRECT]
[Fri Oct 02 06:00:00.919839 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883b8010/initial/redir#1] [perdir /srv/http/projectname/webroot/] strip per-dir prefix: /srv/http/projectname/webroot/index.php -> index.php
[Fri Oct 02 06:00:00.919851 2020] [rewrite:trace3] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883b8010/initial/redir#1] [perdir /srv/http/projectname/webroot/] applying pattern '^' to uri 'index.php'
[Fri Oct 02 06:00:00.919868 2020] [rewrite:trace1] [pid 80730] mod_rewrite.c(483): [client 127.0.0.1:33272] 127.0.0.1 - - [projectname.localhost/sid#5579881cec50][rid#5579883b8010/initial/redir#1] [perdir /srv/http/projectname/webroot/] pass through /srv/http/projectname/webroot/index.php

而对于 NOK,access.log 看起来像这样:

projectname.localhost 127.0.0.1 - - [02/Oct/2020:06:00:00 +0000] "GET /error/404 HTTP/1.1" 404 1131

并且 error.log 不包含任何内容。

因此,也许您知道为什么只有在 URL 路径中使用“错误”并使用 VirtualDocumentRoot 时才会触发此 .htaccess?

谢谢!

标签: phpapache.htaccess

解决方案


只有当我在 URL 中输入 /error/something 和 @anubhava 的提示时才会发生这种情况,这让我检查了 Apache 后台发生的一切。我真的找到了原因。

在 Arch Linux 上使用 Apache 之前,我使用的是 Ubuntu。它在那里工作,所以我比较了所有文件。两个版本都有自定义错误页面的配置文件。

  • Ubuntu:/etc/apache2/conf-available/localized-error-pages.conf
  • 拱门:/etc/httpd/conf/extra/httpd-multilang-errordoc.conf

这两个文件都有一行用于“/error/”的别名。在 Arch 中是这样的:

Alias /error/ "/usr/share/httpd/error/"

但是,对于 Ubuntu,该行已被注释,因此未启用。默认情况下,在原始 Apache 文件和 Xampp 中也启用了错误别名,但在 Ubuntu 和我的网络服务器中默认情况下它被禁用。

由于首先评估配置,因此 URL http://projectname.localhost/error/something将执行别名,并且在目标目录中既没有 .htaccess 文件,也没有名为“something”的文件或目录。所以结果是一个错误页面。我的 webroot 目录中的 .htaccess 文件没有被评估,因为服务器不访问该目录。

我从我的网络服务器知道我不能更改 Apache 配置本身,而只能实现一个 .htaccess 文件。

因此,最好的解决方案(以避免将来发生冲突)是仅使用未在任何默认别名中使用的目录名称。我检查了不同 Apache 包的默认配置文件,这些是一些默认别名:

  • cgi-bin
  • cgi-pub
  • 文档
  • 错误
  • 图标
  • 手动的
  • 上传

希望这些信息也可以帮助其他人。


推荐阅读