Apache 2重写规则错误地更改了URL [英] Apache 2 rewrite rule is incorrectly changing the URL

查看:98
本文介绍了Apache 2重写规则错误地更改了URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请注意,这是我先前提出的问题的重复.但是它最初措辞不佳,经过多次编辑,几乎变成了一个不同的问题,因此我决定提出一个新问题

我有以下文件:

example.dev.conf虚拟主机文件

这是一个非常简单的虚拟主机文件:

This is a very simple vhost file:

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

        <Directory /var/www/example >
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
</VirtualHost>

<VirtualHost *:443>
        ServerName example.dev
        ServerAlias *.example.dev 
        DocumentRoot /var/www/example

        <Directory /var/www/example >
                AllowOverride All
                Order allow,deny
                Allow from all
        </Directory>
</VirtualHost>

.htaccess

以下文件将所有URL重定向到等效的https,除非它以/api/开头.

The following file redirects all urls to the https equivalent, unless it starts with /api/.

还应确保所有路由都使用index.php控制器.

It should also makes sure that ALL routes uses the index.php controller.

RewriteEngine On

# Handle SSL
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/api/ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

问题

这在大多数情况下都是有效的.

The Problem

This works for the most part.

例如http://example.dev/blah重定向到https://example.dev/blah

但是,对于以/api/开头的任何内容,它似乎都无法正常工作.

However, it does not seem to work as expected for anything that starts with /api/.

例如:http://example.dev/api/blah重定向到https://example.dev/index.php时,它根本不应该进行重定向!

For example: http://example.dev/api/blah redirects to https://example.dev/index.php, when it should have not done a redirect at all!

请注意,如果我删除了htaccess文件的最后3行,则重定向工作正常.

Note that the redirects work fine if I remove the final 3 lines of the htaccess file.

我发现有些人发现很难重复我的问题,并坚持在某处还有其他规定.因此,我决定尽我所能显示所有步骤,因此很容易复制:

I have found that some people found it difficult to replicate my problem and have insisted there is some other rule somewhere. Hence I decided to show ALL my steps the best I can so it's very easy to replicate:

vagrant init ubuntu/trusty64
vagrant up --provider virtualbox
vagrant ssh

sudo apt-get install apache2
sudo a2enmod rewrite

cd /etc/apache2/sites-available/
sudo touch example.dev.conf   
# copy contents of the example.dev.conf vhost file as seen above
sudo a2ensite example.dev.conf

cd /var/www/
sudo mkdir example
sudo chown -R www-data:www-data /var/www/example
sudo chmod 777 -R /var/www/example
cd example
echo "test" > index.php
touch .htaccess
# Copy contents of .htaccess file as seen above

sudo chown -R www-data:www-data /var/www/example
sudo chmod 777 -R /var/www/example

sudo service apache2 restart

推荐答案

我认为我设法弄清了这个问题.

I think I managed to figure out the issue.

阅读以下内容: http://httpd.apache.org /docs/current/rewrite/flags.html#flag_l 证明最后一个标志并不一定意味着不再使用其他规则.

Upon reading this: http://httpd.apache.org/docs/current/rewrite/flags.html#flag_l it turns out the last flag doesn't necessarily mean no further rules are used.

例如,对于以下文件:

RewriteEngine On

# Handle SSL
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} !^/api/ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=308]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]

  • /api/blah被重写为index.php
  • 然后再次通过所有规则.根据文档,可能由于以下原因而发生这种情况:
    • /api/blah is rewritten to index.php
    • It then goes through all the rules again. According to the documentation, this can happen for the following reasons:
    • 在处理重写的请求时,可能会再次遇到.htaccess文件或节,因此规则集可能会从头开始再次运行.最常见的情况是,如果其中一条规则导致重定向(内部或外部)导致请求流程重新开始,则将发生这种情况.

      It is possible that as the rewritten request is handled, the .htaccess file or section may be encountered again, and thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect - either internal or external - causing the request process to start over.

      • index.php然后匹配第一个规则,因此将创建到https://example.dev/index.php的重定向.
        • index.php then matches the first rule so a redirect to https://example.dev/index.php is created.
        • 解决方案是改为使用 END标志 (如@anubhava所述,仅Apache 2.4+支持此功能),以防止重新处理规则.

          The solution is to instead use the END flag (which as @anubhava mentioned, is only supported in Apache 2.4+), to prevent the rules being re-processed.

          因此解决方案如下:

          RewriteEngine On
          
          # Handle SSL
          RewriteCond %{HTTPS} off
          RewriteCond %{REQUEST_URI} !^/api/ [NC]
          RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R]
          
          # Handle Front Controller...
          RewriteCond %{REQUEST_FILENAME} !-d
          RewriteCond %{REQUEST_FILENAME} !-f
          RewriteRule ^ index.php [END]
          

          现在,当我进入http://example.dev/api/blah时:

          • 它被重写为index.php
          • 因为它具有END规则,所以不会再次处理这些规则!
          • 因此http://example.dev/api/blah会留在原处,并根据需要使用index.php控制器.
          • It is rewritten to index.php
          • As it has the END rule, the rules are not processed again!
          • Therefore http://example.dev/api/blah stays where it is and uses the index.php controller as desired.

          感谢@Olaf Dietsche让我走上正轨并建议308重定向!

          Thanks @Olaf Dietsche for getting me to the right track and suggesting the 308 redirect!

          这篇关于Apache 2重写规则错误地更改了URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆