Apache 重写到有异常的子目录

Apache rewrite to subdirectory with exceptions

Apache 2.4,我需要创建以下规则并将其放入我的 vhosts 文件中:

  1. 为来自特定目录中文件的特定 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" 提供文件)
  2. 对某些目录忽略此规则(请求“http://www.mydns.com/cache/myjs.js”应该从 "www/cache/" 正常服务)
  3. 如果请求包含 subdir ,忽略规则(请求“http://www.mydns.com/subdir/login.php”正常服务)
  4. 将规则应用于任何 port/protocol(http、https、8080 等其他端口)
  5. 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>