Apache 重写到有异常的子目录
Apache rewrite to subdirectory with exceptions
Apache 2.4,我需要创建以下规则并将其放入我的 vhosts 文件中:
- 为来自特定目录中文件的特定 dns 的所有请求提供服务
(例如,请求“http://www.mydns.com/login.php" should serve the file from subdir "www/subdir/login.php". requesting "http://www.mydns.com/a/b/c/some.php”应该从子目录 "www/subdir/a/b/c/some.php" 提供文件)
- 对某些目录忽略此规则(请求“http://www.mydns.com/cache/myjs.js”应该从 "www/cache/" 正常服务)
- 如果请求包含 subdir ,忽略规则(请求“http://www.mydns.com/subdir/login.php”正常服务)
- 将规则应用于任何 port/protocol(http、https、8080 等其他端口)
- URL 不应该 change/redirect 在用户浏览器上
我一直在尝试在 vhost 文件(每个 dns 一个文件)中使用重写规则,但遇到了很多困难。
非常感谢任何帮助:)
更新
@spacepickle ,感谢您的回复。还是不行,我可能没有提供所有需要的细节,所以就到这里吧。
我将 post 我的 conf 文件和下面的测试。
配置文件:
<VirtualHost *:80>
ServerName my.domain.com
ServerAlias my2.domain.com
DocumentRoot /etc/www
RewriteEngine On
RewriteRule ^/subdir/ - [PT,L]
RewriteRule ^/cache/ - [PT,L]
RewriteRule ^/(.*)$ /subdir/ [PT,L]
</VirtualHost>
获取http://my.domain.com。
预期重写 http://my.domain.com/subdir 。
出现 fcgi 错误:请求的 URL /subdir/php5.fcgi/subdir/index.php 在此服务器上未找到。
获取http://my.domain.com/subdir。
预计不会发生任何事情(忽略重写)。
得到重写:在此服务器上找不到请求的 URL /subdir/subdir。
获取http://my.domain.com/cache。
预计不会发生任何事情(忽略重写)。
得到重写:在此服务器上找不到请求的 URL /subdir/cache。
一个测试用例有效:
获取 http://my.domain.com/clients/tests/index.html 。
预期并重写为:http://my.domain.com/subdir/clients/tests/index.html
更新 有时最好远离 mod_rewrite。我在下面的原始答案使用了 mod_rewrite,但这是一个使用 mod_alias 的更清晰的解决方案,我认为它解决了 OP 的特定用例。 mod_rewrite 解决方案将变得越来越复杂,而使用 mod_alias 应该保持简单(希望如此)。
创建基础-alias.inc 文件
Alias "/subdir" "${DocumentRoot}/subdir"
Alias "/cache" "${DocumentRoot}/cache"
Alias "/" "${DocumentRoot}/subdir/"
然后将其包含在每个虚拟主机定义中,例如:
<VirtualHost *:80>
ServerName www.example.com
Define DocumentRoot /var/www/www
DocumentRoot ${DocumentRoot}
Include base-alias.inc
</VirtualHost>
这里要注意的重要行是 Define DocumentRoot /var/www/www
:这允许您将基本目录传递到包含的文件中。
这应该与 php 一起工作,并且当重定向由 apache 的模块发出时,因为与进一步向下的 mod_rewrite 策略不同,您正在访问的 url 是服务器认为是资源的规范 url。
原始答案使用 mod_rewrite
将以下四行添加到文件中(base-rewrite.inc):
RewriteEngine On
RewriteRule ^/subdir(/.*)? - [PT,L]
RewriteRule ^/cache(/.*)? - [PT,L]
RewriteRule ^/(.*)$ /subdir/ [PT,L]
EDIT 在前两个 url 的末尾添加 (/.*)?
表示,例如,只有子目录作为文件夹(带有或没有斜线)或以下是第一条规则的一部分。这可以防止 /subdirbutnot/hello 之类的东西被匹配
然后从你的虚拟主机中包含这个
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot /var/www/www/
Include base-rewrite.inc
</VirtualHost>
或添加 ServerAlias
行以使用更多名称:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias new.example.com
DocumentRoot /var/www/www/
Include base-rewrite.inc
</VirtualHost>
如果需要,添加更多具有不同文档根目录的虚拟主机
<VirtualHost *:80>
ServerName other.example.com
DocumentRoot /var/www/other/
Include base-rewrite.inc
</VirtualHost>
或更多ports/protocols
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot /var/www/www/
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
Include base-rewrite.inc
</VirtualHost>
另一种但可疑的解决方案
请注意,在一个虚拟主机中,文件夹路径可以由请求的主机名动态决定,但这会评估路径中的环境变量,这是安全漏洞的明确路径。我只是将其展示为所提供灵活性的演示:
base-rewrite-02.inc
RewriteEngine On
RewriteCond "%{ENV:ENV_HOST}" ""
RewriteCond "%{HTTP_HOST}" "!^(www|other)\.example\.com$"
RewriteRule ^/(.*) - [E=ENV_HOST:www]
RewriteCond "%{ENV:ENV_HOST}" ""
RewriteCond "%{HTTP_HOST}" "^(www|other)\.example\.com$"
RewriteRule ^/(.*) - [E=ENV_HOST:%1]
RewriteRule ^/subdir/(.*) /%{ENV:ENV_HOST}/subdir/ [PT,L]
RewriteRule ^/cache/(.*) /%{ENV:ENV_HOST}/cache/ [PT,L]
RewriteRule ^/(.*) /%{ENV:ENV_HOST}/subdir/ [PT,L]
和虚拟主机定义:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias other.example.com
DocumentRoot /var/www/
Include base-rewrite-02.inc
</VirtualHost>
Apache 2.4,我需要创建以下规则并将其放入我的 vhosts 文件中:
- 为来自特定目录中文件的特定 dns 的所有请求提供服务 (例如,请求“http://www.mydns.com/login.php" should serve the file from subdir "www/subdir/login.php". requesting "http://www.mydns.com/a/b/c/some.php”应该从子目录 "www/subdir/a/b/c/some.php" 提供文件)
- 对某些目录忽略此规则(请求“http://www.mydns.com/cache/myjs.js”应该从 "www/cache/" 正常服务)
- 如果请求包含 subdir ,忽略规则(请求“http://www.mydns.com/subdir/login.php”正常服务)
- 将规则应用于任何 port/protocol(http、https、8080 等其他端口)
- URL 不应该 change/redirect 在用户浏览器上
我一直在尝试在 vhost 文件(每个 dns 一个文件)中使用重写规则,但遇到了很多困难。
非常感谢任何帮助:)
更新
@spacepickle ,感谢您的回复。还是不行,我可能没有提供所有需要的细节,所以就到这里吧。 我将 post 我的 conf 文件和下面的测试。
配置文件:
<VirtualHost *:80>
ServerName my.domain.com
ServerAlias my2.domain.com
DocumentRoot /etc/www
RewriteEngine On
RewriteRule ^/subdir/ - [PT,L]
RewriteRule ^/cache/ - [PT,L]
RewriteRule ^/(.*)$ /subdir/ [PT,L]
</VirtualHost>
获取http://my.domain.com。 预期重写 http://my.domain.com/subdir 。 出现 fcgi 错误:请求的 URL /subdir/php5.fcgi/subdir/index.php 在此服务器上未找到。
获取http://my.domain.com/subdir。 预计不会发生任何事情(忽略重写)。 得到重写:在此服务器上找不到请求的 URL /subdir/subdir。
获取http://my.domain.com/cache。 预计不会发生任何事情(忽略重写)。 得到重写:在此服务器上找不到请求的 URL /subdir/cache。
一个测试用例有效: 获取 http://my.domain.com/clients/tests/index.html 。 预期并重写为:http://my.domain.com/subdir/clients/tests/index.html
更新 有时最好远离 mod_rewrite。我在下面的原始答案使用了 mod_rewrite,但这是一个使用 mod_alias 的更清晰的解决方案,我认为它解决了 OP 的特定用例。 mod_rewrite 解决方案将变得越来越复杂,而使用 mod_alias 应该保持简单(希望如此)。
创建基础-alias.inc 文件
Alias "/subdir" "${DocumentRoot}/subdir"
Alias "/cache" "${DocumentRoot}/cache"
Alias "/" "${DocumentRoot}/subdir/"
然后将其包含在每个虚拟主机定义中,例如:
<VirtualHost *:80>
ServerName www.example.com
Define DocumentRoot /var/www/www
DocumentRoot ${DocumentRoot}
Include base-alias.inc
</VirtualHost>
这里要注意的重要行是 Define DocumentRoot /var/www/www
:这允许您将基本目录传递到包含的文件中。
这应该与 php 一起工作,并且当重定向由 apache 的模块发出时,因为与进一步向下的 mod_rewrite 策略不同,您正在访问的 url 是服务器认为是资源的规范 url。
原始答案使用 mod_rewrite
将以下四行添加到文件中(base-rewrite.inc):
RewriteEngine On
RewriteRule ^/subdir(/.*)? - [PT,L]
RewriteRule ^/cache(/.*)? - [PT,L]
RewriteRule ^/(.*)$ /subdir/ [PT,L]
EDIT 在前两个 url 的末尾添加 (/.*)?
表示,例如,只有子目录作为文件夹(带有或没有斜线)或以下是第一条规则的一部分。这可以防止 /subdirbutnot/hello 之类的东西被匹配
然后从你的虚拟主机中包含这个
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot /var/www/www/
Include base-rewrite.inc
</VirtualHost>
或添加 ServerAlias
行以使用更多名称:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias new.example.com
DocumentRoot /var/www/www/
Include base-rewrite.inc
</VirtualHost>
如果需要,添加更多具有不同文档根目录的虚拟主机
<VirtualHost *:80>
ServerName other.example.com
DocumentRoot /var/www/other/
Include base-rewrite.inc
</VirtualHost>
或更多ports/protocols
<VirtualHost *:443>
ServerName www.example.com
DocumentRoot /var/www/www/
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
Include base-rewrite.inc
</VirtualHost>
另一种但可疑的解决方案
请注意,在一个虚拟主机中,文件夹路径可以由请求的主机名动态决定,但这会评估路径中的环境变量,这是安全漏洞的明确路径。我只是将其展示为所提供灵活性的演示:
base-rewrite-02.inc
RewriteEngine On
RewriteCond "%{ENV:ENV_HOST}" ""
RewriteCond "%{HTTP_HOST}" "!^(www|other)\.example\.com$"
RewriteRule ^/(.*) - [E=ENV_HOST:www]
RewriteCond "%{ENV:ENV_HOST}" ""
RewriteCond "%{HTTP_HOST}" "^(www|other)\.example\.com$"
RewriteRule ^/(.*) - [E=ENV_HOST:%1]
RewriteRule ^/subdir/(.*) /%{ENV:ENV_HOST}/subdir/ [PT,L]
RewriteRule ^/cache/(.*) /%{ENV:ENV_HOST}/cache/ [PT,L]
RewriteRule ^/(.*) /%{ENV:ENV_HOST}/subdir/ [PT,L]
和虚拟主机定义:
<VirtualHost *:80>
ServerName www.example.com
ServerAlias other.example.com
DocumentRoot /var/www/
Include base-rewrite-02.inc
</VirtualHost>