Перенаправление https://www.website.com на https://website.com не работает - PullRequest
1 голос
/ 09 марта 2020

Я делаю следующее сообщение о перенаправлении от https://www.website.com до https://website.com:

Проблема с сертификатом Let's Encrypt: https://www.website.com не работает с перенаправлением на https://website.com

Я не могу добиться этого перенаправления, и я не понимаю, в чем причина.

Если я наберу https://www.website.com, он останется на https://www.website.com и не выполнит перенаправление на https://website.com.

Моя конфигурация немного особенная с сервером Zope, работающим с Apache2 .

На данный момент, здесь ниже приведены мои правила перезаписи (http://www.website.com и http//website.com оба перенаправлены в порядке https://website.com):

<VirtualHost *:443>

    # REWRITE to get https://www.website.com to https://website.com except for cgi-bin scripts
    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/cgi-bin/search [NC]
    RewriteCond %{REQUEST_URI} !^/cgi-bin/awstats [NC]
    RewriteRule ^/(.*)  https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]

</VirtualHost>

<VirtualHost *:80>

<IfModule mod_rewrite.c>

# www to non www for HTTP and HTTPS
RewriteCond %{REQUEST_URI} ^/www\. [NC,OR]
RewriteCond %{REQUEST_URI} !^/podcast [NC]
# Rewrite below works : redirect 80 => https
RewriteRule ^/(.*) https://website.com/$1 [R=301,L]

RewriteRule ^/(.*)  http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L]

</IfModule>

</VirtualHost>

Что здесь может быть не так?

1 Ответ

1 голос
/ 12 марта 2020

Я считаю, что есть несколько примечательных вещей :

  1. Один или несколько RewriteCond могут предшествовать директиве RewriteRule. Следующее правило затем используется только в том случае, если текущее состояние URI совпадает с его шаблоном, и если эти условия соблюдены.

  2. Директива RewriteRule ...... может возникнуть больше чем один раз, причем каждый экземпляр определяет одно правило перезаписи. Порядок, в котором определяются эти правила, важен - это порядок, в котором они будут применяться во время выполнения.

  3. В контексте VirtualHost шаблон будет первоначально сопоставляться с часть URL после имени хоста и порта и перед строкой запроса (например, "/app1/index.html"). Это (% -декодированный) URL-путь.

  4. Если вы хотите sh сопоставить имя хоста, порт или строку запроса, используйте RewriteCond с% {HTTP_HOST },% {SERVER_PORT} или% {QUERY_STRING} переменные соответственно.

Вы также используете L | last flags, что делает двигатель прекратите обработку дальнейших правил после запуска RewriteRule.

Вышеупомянутая сортировка дает вам представление о том, как движок выполняет ваши переписывания:

  1. RewriteRules обрабатываются последовательно (если вы не укажете L флаг, который вы делаете для всех правил)
  2. Каждый RewriteRule может иметь множество RewriteCond, которым все должны соответствовать, прежде чем RewriteRule считается. Это также означает, что RewriteCond нужно повторять для каждого RewriteRule индивидуально (однако есть интересная техника для группировки RewriteRules в блоки if-then-else)
  3. В вашем случае (VirtualHost context), по умолчанию сопоставляются только URL-пути, если только вы не сопоставляете переменную HTTP_HOST.

Учитывая это, я вижу несколько проблем с вашими правилами перезаписи (я поменял http и https востребован для читабельности, но это не имеет значения):

<VirtualHost *:80> <!-- your http:// requests will end up with this block, because 80 is the port for http -->
<IfModule mod_rewrite.c>
    # www to non www for HTTP and HTTPS <!-- I believe HTTPS traffic is NOT handled by this vhost at all, it arrives straight to *:443 queue -->
    RewriteCond %{REQUEST_URI} ^/www\. [NC,OR] <!-- you evaluate path component of your request uri to begin with "www." (i.e. /www.index.html) - this will obviously never match, you however have OR flag, which proceeds to the second condition -->
    RewriteCond %{REQUEST_URI} !^/podcast [NC] <!-- you check if the path does not start with "/podcast" - this is easy to test - try http://www.website.com/podcast and see if you get redirected to HTTPS - I suspect you will not -->
    # Rewrite below works : redirect 80 => https <!-- I suspect it works by accident, please test it out with http://www.website.com/podcast to confirm my theory -->
    RewriteRule ^/(.*) https://website.com/$1 [R=301,L] <!-- we end up here, and regardless of the requested path we issue a 301 redirect to https version of the website. This is marked as Last rule, so the engine should stop processing here -->
    RewriteRule ^/(.*)  http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L] <!-- this I believe kicks in when you request a "/podcast" path - this will proxy the request to your http://localhost:9674/ -->
</IfModule>
</VirtualHost>

<VirtualHost *:443><!-- this is where your 301 redirect will com after bouncing through first set of rules above -->
    # REWRITE to get https://www.website.com to https://website.com except for cgi-bin scripts
    RewriteEngine On <!-- this is important, keep it on -->
    RewriteCond %{REQUEST_URI} !^/cgi-bin/search [NC] <!-- you check whether url path does not contain /cgi-bin/search -->
    RewriteCond %{REQUEST_URI} !^/cgi-bin/awstats [NC]<!-- AND does not contain /cgi-bin/awstats-->
    RewriteRule ^/(.*)  https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]<!-- if both conditions above are met - proxy the request to backend and stop further processing. -->
</VirtualHost>

Насколько я вижу - нет правила переписывать https://www.website.com -> https://website.com, единственный бит, который проверяет ваш переписанный https /cgi-bin

Мое предложение будет выглядеть следующим образом (возможно, это не решение для копирования и вставки, но, надеюсь, вы получите суть):

<VirtualHost *:443>    
    RewriteEngine On
    # www to non www for HTTPS
    <!-- checking for the same thing again -->
    RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
    RewriteRule ^/(.*) https://website.com/$1 [R=301,L] <!-- some people might argue second redirect here is excessive since you already arrived at correct host, but I'd leave this for you to sort out -->
    <!-- your /cgi-bin checks can be merged into one regex --> 
    RewriteCond %{REQUEST_URI} !^/cgi-bin/(search|awstats) [NC]
    RewriteRule ^/(.*)  https://localhost:8443/++vh++https:%{SERVER_NAME}:443/++/$1 [P,L]
</VirtualHost>

<VirtualHost *:80>
<IfModule mod_rewrite.c>
    # www to non www for HTTP
    <!-- if you want to keep your `/podcast` on http check it first -->
    RewriteCond %{REQUEST_URI} !^/podcast [NC]
    RewriteRule ^/(.*)  http://localhost:9674/++vh++http:%{SERVER_NAME}:80/++/$1 [P,L]
    <!-- everything else will get redirected to https -->
    RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
    RewriteRule ^/(.*) https://website.com/$1 [R=301,L]
</IfModule>
</VirtualHost>
...