web服务器经过代理后的绝对路径问题,以及 dirname(__FILE__)和__DIR__
问题描述
我有一个部署在自家网络的服务器,为了实现在公网也可以访问(内网穿透),我把web服务通过公网服务器上的 nginx + frp 方案进行了反向代理。实现方式参考这篇文章NGINX配合SSH/FRP反向代理实现内网穿透。
于是在某次使用绝对路径访问文件时,无论如何使用本地服务器上的绝对路径都无法成功访问。(确定内网服务器上的绝对路径是正确的)
情况解析
原因是当我们通过公网服务器的代理服务访问内网服务器上的资源时,如果使用的是内网服务器上的绝对路径,由于套了一层壳,是不能正常访问的。访问者以为的绝对路径将是公网服务器路径与内网服务器路径的一个结合。
资源路径分析
以我的情况举例,使用图表展示的更清晰些。
内网服务器 | 公网服务器 | |
---|---|---|
文件名 | yourplugin.php | default.conf |
文件路径 | /home/user/wordpress/wp-content/plugins/ | /var/www/html |
路径拆分 | 根目录:/home/user/wordpress/ 下级目录:wp-content/plugins/ | 根目录:/var/www/html/ |
内网服务器中需要注意的是(以 wordpress 项目为例),项目的根目录是一定的,项目不同资源分布在根目录下的不同下级目录中。
公网服务器中关键的是 nginx 配置文件中设置的 root 位置,我的设置是 /var/www/html。具体可见NGINX 多域名访问多端口应用。
访问过程分析
以上文情况举例,我想访问 wordpress 项目下的 yourplugin.php 文件,需要使用下面这个 url。
URL:https://www.domain.com/wordpress/yourplugin
域名 | 后续字段 | |
---|---|---|
URL | www.domain.com | wordpress/yourplugin |
资源路径 | 根目录 | 下级目录 |
当我们通过 url 来访问 web 资源时,域名(形如 www.domain.com) 被 nginx 等 web 程序解析到根目录的位置;后续字段代表的是资源所在的下级目录。这样我们才可以通过 url 从世界各地都能访问到特定服务器上的特定文件。
此时关注内网穿透情况下的访问过程:
此时路径结构就清晰了,考虑绝对路径 = 根目录 + 下级目录,注意此时根目录是在公网服务器上解析的,下级目录是在内网服务器上解析的,所以:
内网穿透下绝对路径 = 公网服务器根目录 + 内网服务器下级目录
参考文章第一个表格,重要路径已经粗体强调,yourplugin.php 的绝对路径应该为:/var/www/html/wp-content/plugins/yourplugin.php
。
dirname(__FILE__) 与 __DIR__
通过上述解析我们的确可以对每个资源都设置出可用的绝对路径,但是在编程时采取此法则不甚明智。因为一些项目迁移等原因很容易使得路径失效,并且也不方便。
在 php 中,我们可以使用 dirname(__FILE__) 和 __DIR__ 来方便的获取当前资源的绝对路径。
- dirname(__FILE__)
获取当前资源所在的目录的绝对路径,例如/var/www/html/wp-content/plugins
。 - __DIR__
获取当前资源本身的绝对路径,例如/var/www/html/wp-content/plugins/yourplugin.php
。
常用方法:
#如果只是想调用这个文件本身,那么可以使用:
$filepath = __DIR__;
#如果是想访问当前文件同一目录下的资源,那么可以使用:
$filepath = dirname(__FILE__) . '/text.txt';
#注意后缀的字符串需要有 / 。因为dirname最后一位不是 / ,需要我们补全。