重定向如果REQUEST_URI以某事开头

时间:2013-11-21 10:27:05

标签: apache .htaccess mod-rewrite

我有两个子域api.example.netwww.example.net。如果api.example.net不以www.example.net开头(例如REQUEST_URI/v1/),我想从/v1/token重定向到/v1/status/update

/etc/apache2/sites-enabled中的配置文件是这样的。

<VirtualHost *:443>
    ServerName api.example.net
    DocumentRoot /var/www

    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/v1/
    RewriteRule (.*) http://www.example.net%{REQUEST_URI} [R=301,L]

    <Directory /var/www>
        Options Indexes FollowSymLinks Includes
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

但是当我尝试

petra@petra-laptop:~$ curl -XGET -k 'https://api.example.net/test'

它返回了

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.example.net/test">here</a>.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at api.example.net Port 443</address>
</body></html>

这就是我的预期。

但是当我尝试

petra@petra-laptop:~$ curl -XGET -k 'https://api.example.net/v1/token'

它返回了

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.example.net/index.php">here</a>.</p>
<hr>
<address>Apache/2.2.22 (Ubuntu) Server at api.example.net Port 443</address>
</body></html>

我预计它会传递给https://api.example.net/v1/token

我在这里尝试了代码http://htaccess.madewithlove.be/,它返回了我的预期。

我做错了什么?

更新

该项目正在使用Yii Framework,因此在/var/www内部有.htaccess个文件。

RewriteEngine on
RewriteBase /

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule . index.php

3 个答案:

答案 0 :(得分:2)

我假设您的框架需要处理令牌(换句话说:.htaccess 中的规则必须匹配)。

我猜测(但不是100%肯定),在下一次传递期间,网址再次与虚拟主机中的规则匹配。因为网址是index.php而不是v1/token,所以虚拟主机中的规则匹配。要确保规则仅匹配原始网址(请求中的网址),请改用%{THE_REQUEST}

<VirtualHost *:443>
    ServerName api.example.net
    DocumentRoot /var/www

    RewriteEngine On
    RewriteCond %{THE_REQUEST} !^(GET|POST)\ /v1/
    RewriteRule ^ http://www.example.net%{REQUEST_URI} [R=301,L]

    <Directory /var/www>
        Options Indexes FollowSymLinks Includes
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>

因为这是在主配置文件中,所以您必须重新启动Apache才能使更改生效。

答案 1 :(得分:1)

请你试试那个(我希望我没有遗漏一些东西):

RewriteCond %{HTTP_HOST} ^api\.example\.net$ [NC]
RewriteCond %{REQUEST_URI} !^v1/
RewriteRule (.*) http://www.example.net/$1 [R=301,L]

如果将其放在vhost中,则可能必须重新启动Apache才能使更改生效。

如果你把它放在.htaccess文件中(你至少可以把它放在测试中),你应该把它放在“RewriteCond%{REQUEST_FILENAME}!-f”之前。

编辑:我想我明白了! 你会说它不起作用(再次),因为你正在测试一个不指向文件或目录的URL(!!!),然后当文件/目录没有如果存在,请求将再次重定向到index.php。

我在一个子域+另一个安装了WP的域上进行了测试,看起来该文件不存在我正被重定向到主域(安装和配置WP的地方)。当我使用现有文件时,重定向工作正常!

如果它不起作用,你有没有选择在另一台服务器或同一台服务器上测试它,但是使用另一个文档根目录,你只需要上面的重写来测试它们与其他服务器分开规则?

让我知道结果是什么!

答案 2 :(得分:-1)

我错过了你的错误,你做错了!^ / v1 /

应该是! ^ / V1 /:

<VirtualHost *:443>
    ServerName api.example.net
    DocumentRoot /var/www

    RewriteEngine On
    RewriteCond %{REQUEST_URI} ! ^/v1/:
    RewriteRule (.*) http://www.example.net%{REQUEST_URI} [R=301,L]

    <Directory /var/www>
        Options Indexes FollowSymLinks Includes
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>