Apache rewrite to subdirectory with exceptions

时间:2017-04-06 16:58:29

标签: url mod-rewrite url-rewriting apache2

Apache 2.4, I need to create the following rule and place it in my vhosts file :

  1. Serve all requests from a certain dns from files in a specific dir (examples, requesting "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" should serve the file from subdir "www/subdir/a/b/c/some.php")
  2. Ignore this rule for some directories (requesting "http://www.mydns.com/cache/myjs.js" should serve normally from "www/cache/")
  3. If the request contains the subdir , ignore the rule (requesting "http://www.mydns.com/subdir/login.php" serves normally)
  4. Apply the rule to any port/protocol (http, https, other ports like 8080)
  5. URL's should not change/redirect on the users browser

I've been trying to use rewrite rules inside a vhost file (one file for each dns) but been having a very hard time with it.

Any help is greatly appreciated :)

Update

@spacepickle , thanks for the reply. Still no go, I may have not given all the needed details so here it goes. I will post my conf file and the tests right below.

conf file :

<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/$1 [PT,L]   
</VirtualHost>

GET http://my.domain.com . expected rewrite http://my.domain.com/subdir . got fcgi error : The requested URL /subdir/php5.fcgi/subdir/index.php was not found on this server.

GET http://my.domain.com/subdir . expected nothing happening (ignore rewrite) . got rewrite : The requested URL /subdir/subdir was not found on this server.

GET http://my.domain.com/cache . expected nothing happening (ignore rewrite) . got rewrite : The requested URL /subdir/cache was not found on this server.

One test case worked : GET http://my.domain.com/clients/tests/index.html . expected and got rewrite to : http://my.domain.com/subdir/clients/tests/index.html

1 个答案:

答案 0 :(得分:0)

更新有时最好远离mod_rewrite。我下面的原始答案使用了mod_rewrite,但是使用mod_alias是一个更干净的解决方案,我认为它解决了OP的具体用例。 mod_rewrite解决方案会变得越来越复杂,而使用mod_alias应该保持简单(希望如此)。

创建一个base-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/$1 [PT,L]

编辑(/.*)?添加到前两个网址的末尾,例如,只有subir作为文件夹(带或不带斜线)或下面是第一个的一部分规则。这可以防止/ 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>

如果需要,添加更多具有不同Document根目录的虚拟主机

<VirtualHost *:80>
    ServerName other.example.com
    DocumentRoot /var/www/other/

    Include base-rewrite.inc
</VirtualHost>

或更多端口/协议

<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/$1 [PT,L]
RewriteRule ^/cache/(.*) /%{ENV:ENV_HOST}/cache/$1 [PT,L]
RewriteRule ^/(.*) /%{ENV:ENV_HOST}/subdir/$1 [PT,L]

虚拟主机定义:

<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias other.example.com
    DocumentRoot /var/www/

    Include base-rewrite-02.inc
</VirtualHost>