php - 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 没有被执行。
所以我做了一些测试并得到了这个结果(在括号中你可以看到重定向是否有效以及服务器回复状态代码):
- http://projectname.localhost/error [OK 200]
- http://projectname.localhost/error/404 [NOK 404]
- http://projectname.localhost/error/?test [NOK 403]
- http://projectname.localhost/error?test [OK 200]
- http://projectname.localhost/something [OK 200]
- http://projectname.localhost/something/404 [OK 200]
- http://projectname.localhost/something/?test [OK 200]
- http://projectname.localhost/something?test [OK 200]
- http://localhost/projectname/webroot/error [OK 200]
- http://localhost/projectname/webroot/error/404 [OK 200]
- http://localhost/projectname/webroot/error/?test [OK 200]
- http://localhost/projectname/webroot/error?test [OK 200]
- http://localhost/projectname/webroot/something [OK 200]
- http://localhost/projectname/webroot/something/404 [OK 200]
- http://localhost/projectname/webroot/something/?test [OK 200]
- http://localhost/projectname/webroot/something?test [OK 200]
仅当我使用 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?
谢谢!
解决方案
只有当我在 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
- 文档
- 错误
- 图标
- 手动的
- 上传
希望这些信息也可以帮助其他人。
推荐阅读
- php - 为 eloquent 模型添加属性
- django - Django Admin中没有对象实例的内联操作
- python - 如何将字符串分割成嵌套列表中的单个字符
- java - 尝试从 SQLite DB 设置 checkedtextview 时出错
- asp.net-core-2.0 - 如何在 asp.net 核心框架中使用 DocuSign 对文档进行数字签名
- r - 从 R 中的异常库运行 time_decompose 函数时收到错误消息
- ios - 如何更改 statusBarFrame 颜色以与 Swift iOS 13 中的 NavigationController 保持相同
- c++ - C++ 通过vector.resize() 和vector.reserve() 从函数返回向量
- glob - 为什么GLOB叫GLOB?它的完整形式是什么?
- javascript - 在反应中将json保存在html li中