我没有看到任何帖子讨论REQUEST_URI
和之间的区别REQUEST_FILENAME
,尽管我看到许多帖子互换使用它们。
我打开mod_rewrite
日志(LogLevel alert rewrite:trace8
),替换REQUEST_FILENAME
为REQUEST_FILENAME
,查看了各个配置中的重写日志,重写过程完全相同。
所以我的问题是:
在 99% 的情况下它们是否都一样?
我没有说 100%,因为我从文档中看到(https://httpd.apache.org/docs/current/mod/mod_rewrite.htmlREQUEST_URI
) 提到与某事相关的例外AcceptPathInfo
。
请求文件名
如果服务器当时已确定此路径,则引用与请求匹配的文件或脚本的完整本地文件系统路径
REQUEST_FILENAME
。否则,例如在虚拟主机上下文中使用时,与 的值相同REQUEST_URI
。 根据 的值AcceptPathInfo
,服务器可能仅使用了 的一些主要组件将REQUEST_URI
请求映射到文件。
实际上,我发现很难理解整个定义,而不仅仅是最后一句话。
我主要在REQUEST_FILENAME
和之间使用。REQUEST_URI
<VirtualHost *:443>
我的<VirtualHost *:443>
设置:
<VirtualHost *:443>
ServerAdmin [email protected]
DocumentRoot /var/www/example.com/public_html
ServerName example.com
ServerAlias www.example.com
LogLevel alert rewrite:trace8
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine On
#RewriteCond %{REQUEST_URI} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule (.*) /tq_info.php?p=%{REQUSET_URI}
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !/.*\.php$
RewriteCond %{REQUEST_FILENAME} !/admin/.*
RewriteRule (.*) /index.php/$1 [L]
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
</VirtualHost>
答案1
我迟到了,但需要澄清一些事情:
REQUEST_URI
, 作为迈克尔·汉普顿 写道,始终包含所请求 URI 的路径部分。至关重要的是,这意味着查询参数(例如?a=b
)将从请求 URI 中剥离。
REQUEST_FILENAME
是一隻野獸。
在最佳情况下,它将包含一个映射到所请求内容的本地文件系统路径,并且它将完全是%{DOCUMENT_ROOT}%{REQUEST_URI}
。但情况不一定如此。如果%{REQUEST_URI}
映射到别名,它将被透明地重定向,因此%{REQUEST_FILENAME}
也会有所不同。这也适用于重定向链,例如/
➜/tricked/you
后者的路径实际上存在(相对于文档根目录)。有人可能会说这是一个我们可以忽略的中间步骤,但链接是可能的。
然后,AcceptPathInfo
配置选项修改请求 URI 映射到文件的方式。如果设置为on
,服务器还会扫描文件中的子路径,并在 中公开尾随数据%{PATH_INFO}
。在这种情况下,只有 的一部分%{REQUEST_URI}
可用于将路径映射到文件系统位置。扩展上面的示例,如果/tricked/you
指的是正确的文件,%{REQUEST_URI}
会让/tricked/you/and/then/some/more
httpd 将请求映射到本来/tricked/you
会映射到 并公开/and/then/some/more
为 的内容%{PATH_INFO}
,这意味着%{REQUEST_FILENAME}
最终会是 之类的东西%{DOCUMENT_ROOT}/tricked/you
。
最后,是否%{REQUEST_FILENAME}
已经扩展为实际的文件系统路径或仍然设置为%{REQUEST_URI}
取决于语境它的用法。在VirtualHost
您正在使用的上下文中,它永远不会是映射的文件系统路径 - 主要是因为这个代码点位于代码路径中的实际映射点之前。遗憾的是,没有简单的方法可以找出 httpd 是否可能已经(部分)映射%{REQUEST_URI}
到文件系统位置 - 除了查看源代码并希望执行路径不会意外更改之外。
不过,您可以放心地做出以下几个假设:
VirtualHost
上下文只会看到未映射的值- 在属于文档根目录的脚本中查询该变量将始终返回映射路径(因为,如果其位置未事先映射,httpd 还能如何执行该脚本?)
其余一切都是反复试验。尤其是,%{REQUEST_FILENAME}
不需要映射到任何随机执行的脚本。考虑包装器,当设置为处理程序时,它实际上确定要提供或执行哪个文件。
答案2
它们非常不同并且有不同的用途。
REQUEST_URI 是请求中 URI 的路径部分。例如,/tq_info.php
。
REQUEST_FILENAME 是尝试通过将 URI 路径应用于文档根目录或可能已定义的任何别名来在本地文件系统中查找文件的结果。因此,如果文件存在,它将被设置为/var/www/example.com/public_html/tq_info.php
。它用于在文件系统中定位文件。只有当文件系统中没有文件时,它才会设置为匹配 REQUEST_URI。在这种情况下,请求将被传递给 404 处理程序,或者传递给上游 Web 应用程序(如果您在 Web 服务器配置中定义了与 URI 路径匹配的应用程序)。
当您选择使用哪一个时,您需要考虑您是否尝试使用 URI 路径组件,或者文件系统中相应文件的路径。