Я считаю, что есть несколько примечательных вещей :
Один или несколько RewriteCond могут предшествовать директиве RewriteRule. Следующее правило затем используется только в том случае, если текущее состояние URI совпадает с его шаблоном, и если эти условия соблюдены.
Директива RewriteRule ...... может возникнуть больше чем один раз, причем каждый экземпляр определяет одно правило перезаписи. Порядок, в котором определяются эти правила, важен - это порядок, в котором они будут применяться во время выполнения.
В контексте VirtualHost шаблон будет первоначально сопоставляться с часть URL после имени хоста и порта и перед строкой запроса (например, "/app1/index.html"). Это (% -декодированный) URL-путь.
Если вы хотите sh сопоставить имя хоста, порт или строку запроса, используйте RewriteCond с% {HTTP_HOST },% {SERVER_PORT} или% {QUERY_STRING} переменные соответственно.
Вы также используете L | last flags, что делает двигатель прекратите обработку дальнейших правил после запуска RewriteRule
.
Вышеупомянутая сортировка дает вам представление о том, как движок выполняет ваши переписывания:
RewriteRules
обрабатываются последовательно (если вы не укажете L
флаг, который вы делаете для всех правил) - Каждый
RewriteRule
может иметь множество RewriteCond
, которым все должны соответствовать, прежде чем RewriteRule
считается. Это также означает, что RewriteCond
нужно повторять для каждого RewriteRule
индивидуально (однако есть интересная техника для группировки RewriteRules в блоки if-then-else) - В вашем случае (
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>