简体   繁体   中英

Strange behaviour with Apache VirtualHost rewrite rules and htaccess

I have this problem I haven't figured it out yet, maybe you could give me a hand with it.

<VirtualHost *:80>

    ServerName example.com
    ServerAlias www.example.com

    DocumentRoot "/var/www/example.com/current/web/"

    RewriteEngine On

    RewriteLog "/var/log/apache2/rewrite.log"
    RewriteLogLevel 3

    RewriteCond %{REQUEST_URI} !^/api/special/url/token
    RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
    RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]

    RewriteCond %{REQUEST_URI} !^/api/special/url/token
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]

</VirtualHost>

This is my VirtualHost configuration, I need to redirect everything to the HTTPS protocol, except for one specific URL.

This VirtualHost rules are working OK. Problem is, when this goes to the DocumentRoot where there is an .htaccess file (from Symfony2 standard edition), a strange behaviour is produced. Here is the .htaccess file:

DirectoryIndex app.php

RewriteEngine On

RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

RewriteRule .? %{ENV:BASE}/app.php [L]

And here is the RewriteLog log:

[example.com/sid#b740c280][rid#b62df058/initial] (2) init rewrite engine with requested uri /api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) applying pattern '(.*)' to uri '/api/special/url/token'
[example.com/sid#b740c280][rid#b62df058/initial] (3) applying pattern '(.*)' to uri '/api/special/url/token'
[example.com/sid#b740c280][rid#b62df058/initial] (1) pass through /api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] add path info postfix: /var/www/example.com/current/web/api -> /var/www/example.com/current/web/api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] strip per-dir prefix: /var/www/example.com/current/web/api/special/url/token -> api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] applying pattern '^(.*)' to uri 'api/special/url/token'
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] add path info postfix: /var/www/example.com/current/web/api -> /var/www/example.com/current/web/api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] strip per-dir prefix: /var/www/example.com/current/web/api/special/url/token -> api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] applying pattern '.?' to uri 'api/special/url/token'
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] add path info postfix: /var/www/example.com/current/web/api -> /var/www/example.com/current/web/api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] strip per-dir prefix: /var/www/example.com/current/web/api/special/url/token -> api/special/url/token
[example.com/sid#b740c280][rid#b62df058/initial] (3) [perdir /var/www/example.com/current/web/] applying pattern '.?' to uri 'api/special/url/token'
[example.com/sid#b740c280][rid#b62df058/initial] (2) [perdir /var/www/example.com/current/web/] rewrite 'api/special/url/token' -> '/app.php'
[example.com/sid#b740c280][rid#b62df058/initial] (1) [perdir /var/www/example.com/current/web/] internal redirect with /app.php [INTERNAL REDIRECT]
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (2) init rewrite engine with requested uri /app.php
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (3) applying pattern '(.*)' to uri '/app.php'
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (2) rewrite '/app.php' -> 'https://www.example.com/app.php'
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (2) explicitly forcing redirect with https://www.example.com/app.php
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (1) escaping https://www.example.com/app.php for redirect
[example.com/sid#b740c280][rid#b6291310/initial/redir#1] (1) redirect to https://www.example.com/app.php [REDIRECT/301]

The expected behaviour is, when this specific URL is matched, it doesn't redirect to the HTTPS URL, and also the petition is handled as a normal one by the Symfony2 frontend controller.

Thanks in advance.

I think the issue is that the first configuration is in the virtual host, the second one is in the .htaccess in the folder, htaccess has priorities, lets consider this structure

├──folder1
│  ├── .htaccess1
│  ├── folder2
│  │   ├── .htaccess2
│  │   ├── folder3
│  │   │   ├──.htaccess 3

The rules inside .htaccess1 will be overridden by .htaccess2 , and both will be overridden by options inside .htaccess3 , the last priority is for the options inside the virtualhost it self.

So I assume there would be only 2 options, either move your rewrites from the virtualhost level into the symfony .htaccess file, or try escaping them by a condition from the .htaccess and wait for them to bubble back up to the virtualhost to apply the rules there.

I think a combined .htaccess like this would do the trick

DirectoryIndex app.php

RewriteEngine On

# https redirections
RewriteCond %{REQUEST_URI} !^/api/special/url/token
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule (.*) https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]

RewriteCond %{REQUEST_URI} !^/api/special/url/token
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,QSA]

# symfony2 rewriting
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

RewriteRule .? %{ENV:BASE}/app.php [L]

I got a comment though, I don't really understand what you're trying to do, you keep redirecting back and forth between www and non-www ?

Problem is that Symhony's front controller /app.php also gets redirected to HTTPS since RewriteCond %{REQUEST_URI} !^/api/special/url/token still holds true. Replace your VirtualHost rules as this:

RewriteCond %{REQUEST_URI} !^/(api/special/url/token|app\.php)
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]

RewriteCond %{REQUEST_URI} !^/(api/special/url/token|app\.php)
RewriteCond %{HTTP_HOST} ^www\..+$ [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]

Don't forget to restart your Apache server after making this change. Once that is done that unwanted redirection to HTTPS will be stopped.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM